home *** CD-ROM | disk | FTP | other *** search
/ Nautilus 1992 July / Nautilus-3-8 / Nautilus-3-8.bin / Tools & Utilities / Techy Stuff / Development Environments ƒ / Perl 4.0.2 ƒ / eval.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-05  |  136.1 KB  |  5,606 lines

  1. /* $RCSfile: eval.c,v $$Revision: 4.0.1.3 $$Date: 91/11/05 17:15:21 $
  2.  *
  3.  *    Copyright (c) 1991, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  * $Log:    eval.c,v $
  9.  * Revision 4.0.1.3  91/11/05  17:15:21  lwall
  10.  * patch11: prepared for ctype implementations that don't define isascii()
  11.  * patch11: various portability fixes
  12.  * patch11: added sort {} LIST
  13.  * patch11: added eval {}
  14.  * patch11: sysread() in socket was substituting recv()
  15.  * patch11: a last statement outside any block caused occasional core dumps
  16.  * patch11: missing arguments caused core dump in -D8 code
  17.  * patch11: eval 'stuff' now optimized to eval {stuff}
  18.  * 
  19.  * Revision 4.0.1.2  91/06/07  11:07:23  lwall
  20.  * patch4: new copyright notice
  21.  * patch4: length($`), length($&), length($') now optimized to avoid string copy
  22.  * patch4: assignment wasn't correctly de-tainting the assigned variable.
  23.  * patch4: default top-of-form format is now FILEHANDLE_TOP
  24.  * patch4: added $^P variable to control calling of perldb routines
  25.  * patch4: taintchecks could improperly modify parent in vfork()
  26.  * patch4: many, many itty-bitty portability fixes
  27.  * 
  28.  * Revision 4.0.1.1  91/04/11  17:43:48  lwall
  29.  * patch1: fixed failed fork to return undef as documented
  30.  * patch1: reduced maximum branch distance in eval.c
  31.  * 
  32.  * Revision 4.0  91/03/20  01:16:48  lwall
  33.  * 4.0 baseline.
  34.  * 
  35.  */
  36.  
  37. #include "EXTERN.h"
  38. #include "perl.h"
  39.  
  40. #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
  41. #include <signal.h>
  42. #endif
  43.  
  44. #ifdef I_FCNTL
  45. #include <fcntl.h>
  46. #endif
  47. #ifdef I_SYS_FILE
  48. #include <sys/file.h>
  49. #endif
  50. #ifdef I_VFORK
  51. #   include <vfork.h>
  52. #endif
  53.  
  54. #ifdef VOIDSIG
  55. static void (*ihand)();
  56. static void (*qhand)();
  57. #else
  58. static int (*ihand)();
  59. static int (*qhand)();
  60. #endif
  61.  
  62. ARG *debarg;
  63. STR str_args;
  64. static STAB *stab2;
  65. static STIO *stio;
  66. static struct lstring *lstr;
  67. static int old_rschar;
  68. static int old_rslen;
  69.  
  70. char *getlogin();
  71.  
  72. #ifndef macintosh
  73.  
  74. double sin(), cos(), atan2(), pow();
  75.  
  76. int
  77. eval(arg,gimme,sp)
  78. register ARG *arg;
  79. int gimme;
  80. register int sp;
  81. {
  82.     register STR *str;
  83.     register int anum;
  84.     register int optype;
  85.     register STR **st;
  86.     int maxarg;
  87.     double value;
  88.     register char *tmps;
  89.     char *tmps2;
  90.     int argflags;
  91.     int argtype;
  92.     union argptr argptr;
  93.     int arglast[8];    /* highest sp for arg--valid only for non-O_LIST args */
  94.     unsigned long tmplong;
  95.     long when;
  96.     FILE *fp;
  97.     STR *tmpstr;
  98.     FCMD *form;
  99.     STAB *stab;
  100.     ARRAY *ary;
  101.     bool assigning = FALSE;
  102.     double exp(), log(), sqrt(), modf();
  103.     char *crypt(), *getenv();
  104.     extern void grow_dlevel();
  105.  
  106.     if (!arg)
  107.     goto say_undef;
  108.     optype = arg->arg_type;
  109.     maxarg = arg->arg_len;
  110.     arglast[0] = sp;
  111.     str = arg->arg_ptr.arg_str;
  112.     if (sp + maxarg > stack->ary_max)
  113.     astore(stack, sp + maxarg, Nullstr);
  114.     st = stack->ary_array;
  115.  
  116. #ifdef DEBUGGING
  117.     if (debug) {
  118.     if (debug & 8) {
  119.         deb("%s (%lx) %d args:\n",opname[optype],arg,maxarg);
  120.     }
  121.     debname[dlevel] = opname[optype][0];
  122.     debdelim[dlevel] = ':';
  123.     if (++dlevel >= dlmax)
  124.         grow_dlevel();
  125.     }
  126. #endif
  127.  
  128.     for (anum = 1; anum <= maxarg; anum++) {
  129.     argflags = arg[anum].arg_flags;
  130.     argtype = arg[anum].arg_type;
  131.     argptr = arg[anum].arg_ptr;
  132.       re_eval:
  133.     switch (argtype) {
  134.     default:
  135.         st[++sp] = &str_undef;
  136. #ifdef DEBUGGING
  137.         tmps = "NULL";
  138. #endif
  139.         break;
  140.     case A_EXPR:
  141. #ifdef DEBUGGING
  142.         if (debug & 8) {
  143.         tmps = "EXPR";
  144.         deb("%d.EXPR =>\n",anum);
  145.         }
  146. #endif
  147.         sp = eval(argptr.arg_arg,
  148.         (argflags & AF_ARYOK) ? G_ARRAY : G_SCALAR, sp);
  149.         if (sp + (maxarg - anum) > stack->ary_max)
  150.         astore(stack, sp + (maxarg - anum), Nullstr);
  151.         st = stack->ary_array;    /* possibly reallocated */
  152.         break;
  153.     case A_CMD:
  154. #ifdef DEBUGGING
  155.         if (debug & 8) {
  156.         tmps = "CMD";
  157.         deb("%d.CMD (%lx) =>\n",anum,argptr.arg_cmd);
  158.         }
  159. #endif
  160.         sp = cmd_exec(argptr.arg_cmd, gimme, sp);
  161.         if (sp + (maxarg - anum) > stack->ary_max)
  162.         astore(stack, sp + (maxarg - anum), Nullstr);
  163.         st = stack->ary_array;    /* possibly reallocated */
  164.         break;
  165.     case A_LARYSTAB:
  166.         ++sp;
  167.         switch (optype) {
  168.         case O_ITEM2: argtype = 2; break;
  169.         case O_ITEM3: argtype = 3; break;
  170.         default:      argtype = anum; break;
  171.         }
  172.         str = afetch(stab_array(argptr.arg_stab),
  173.         arg[argtype].arg_len - arybase, TRUE);
  174. #ifdef DEBUGGING
  175.         if (debug & 8) {
  176.         (void)sprintf(buf,"LARYSTAB $%s[%d]",stab_name(argptr.arg_stab),
  177.             arg[argtype].arg_len);
  178.         tmps = buf;
  179.         }
  180. #endif
  181.         goto do_crement;
  182.     case A_ARYSTAB:
  183.         switch (optype) {
  184.         case O_ITEM2: argtype = 2; break;
  185.         case O_ITEM3: argtype = 3; break;
  186.         default:      argtype = anum; break;
  187.         }
  188.         st[++sp] = afetch(stab_array(argptr.arg_stab),
  189.         arg[argtype].arg_len - arybase, FALSE);
  190. #ifdef DEBUGGING
  191.         if (debug & 8) {
  192.         (void)sprintf(buf,"ARYSTAB $%s[%d]",stab_name(argptr.arg_stab),
  193.             arg[argtype].arg_len);
  194.         tmps = buf;
  195.         }
  196. #endif
  197.         break;
  198.     case A_STAR:
  199.         stab = argptr.arg_stab;
  200.         st[++sp] = (STR*)stab;
  201.         if (!stab_xarray(stab))
  202.         aadd(stab);
  203.         if (!stab_xhash(stab))
  204.         hadd(stab);
  205.         if (!stab_io(stab))
  206.         stab_io(stab) = stio_new();
  207. #ifdef DEBUGGING
  208.         if (debug & 8) {
  209.         (void)sprintf(buf,"STAR *%s",stab_name(argptr.arg_stab));
  210.         tmps = buf;
  211.         }
  212. #endif
  213.         break;
  214.     case A_LSTAR:
  215.         str = st[++sp] = (STR*)argptr.arg_stab;
  216. #ifdef DEBUGGING
  217.         if (debug & 8) {
  218.         (void)sprintf(buf,"LSTAR *%s",stab_name(argptr.arg_stab));
  219.         tmps = buf;
  220.         }
  221. #endif
  222.         break;
  223.     case A_STAB:
  224.         st[++sp] = STAB_STR(argptr.arg_stab);
  225. #ifdef DEBUGGING
  226.         if (debug & 8) {
  227.         (void)sprintf(buf,"STAB $%s",stab_name(argptr.arg_stab));
  228.         tmps = buf;
  229.         }
  230. #endif
  231.         break;
  232.     case A_LENSTAB:
  233.         str_numset(str, (double)STAB_LEN(argptr.arg_stab));
  234.         st[++sp] = str;
  235. #ifdef DEBUGGING
  236.         if (debug & 8) {
  237.         (void)sprintf(buf,"LENSTAB $%s",stab_name(argptr.arg_stab));
  238.         tmps = buf;
  239.         }
  240. #endif
  241.         break;
  242.     case A_LEXPR:
  243. #ifdef DEBUGGING
  244.         if (debug & 8) {
  245.         tmps = "LEXPR";
  246.         deb("%d.LEXPR =>\n",anum);
  247.         }
  248. #endif
  249.         if (argflags & AF_ARYOK) {
  250.         sp = eval(argptr.arg_arg, G_ARRAY, sp);
  251.         if (sp + (maxarg - anum) > stack->ary_max)
  252.             astore(stack, sp + (maxarg - anum), Nullstr);
  253.         st = stack->ary_array;    /* possibly reallocated */
  254.         }
  255.         else {
  256.         sp = eval(argptr.arg_arg, G_SCALAR, sp);
  257.         st = stack->ary_array;    /* possibly reallocated */
  258.         str = st[sp];
  259.         goto do_crement;
  260.         }
  261.         break;
  262.     case A_LVAL:
  263. #ifdef DEBUGGING
  264.         if (debug & 8) {
  265.         (void)sprintf(buf,"LVAL $%s",stab_name(argptr.arg_stab));
  266.         tmps = buf;
  267.         }
  268. #endif
  269.         ++sp;
  270.         str = STAB_STR(argptr.arg_stab);
  271.         if (!str)
  272.         fatal("panic: A_LVAL");
  273.       do_crement:
  274.         assigning = TRUE;
  275.         if (argflags & AF_PRE) {
  276.         if (argflags & AF_UP)
  277.             str_inc(str);
  278.         else
  279.             str_dec(str);
  280.         STABSET(str);
  281.         st[sp] = str;
  282.         str = arg->arg_ptr.arg_str;
  283.         }
  284.         else if (argflags & AF_POST) {
  285.         st[sp] = str_mortal(str);
  286.         if (argflags & AF_UP)
  287.             str_inc(str);
  288.         else
  289.             str_dec(str);
  290.         STABSET(str);
  291.         str = arg->arg_ptr.arg_str;
  292.         }
  293.         else
  294.         st[sp] = str;
  295.         break;
  296.     case A_LARYLEN:
  297.         ++sp;
  298.         stab = argptr.arg_stab;
  299.         str = stab_array(argptr.arg_stab)->ary_magic;
  300.         if (optype != O_SASSIGN || argflags & (AF_PRE|AF_POST))
  301.         str_numset(str,(double)(stab_array(stab)->ary_fill+arybase));
  302. #ifdef DEBUGGING
  303.         tmps = "LARYLEN";
  304. #endif
  305.         if (!str)
  306.         fatal("panic: A_LEXPR");
  307.         goto do_crement;
  308.     case A_ARYLEN:
  309.         stab = argptr.arg_stab;
  310.         st[++sp] = stab_array(stab)->ary_magic;
  311.         str_numset(st[sp],(double)(stab_array(stab)->ary_fill+arybase));
  312. #ifdef DEBUGGING
  313.         tmps = "ARYLEN";
  314. #endif
  315.         break;
  316.     case A_SINGLE:
  317.         st[++sp] = argptr.arg_str;
  318. #ifdef DEBUGGING
  319.         tmps = "SINGLE";
  320. #endif
  321.         break;
  322.     case A_DOUBLE:
  323.         (void) interp(str,argptr.arg_str,sp);
  324.         st = stack->ary_array;
  325.         st[++sp] = str;
  326. #ifdef DEBUGGING
  327.         tmps = "DOUBLE";
  328. #endif
  329.         break;
  330.     case A_BACKTICK:
  331.         tmps = str_get(interp(str,argptr.arg_str,sp));
  332.         st = stack->ary_array;
  333. #ifdef TAINT
  334.         taintproper("Insecure dependency in ``");
  335. #endif
  336.         fp = mypopen(tmps,"r");
  337.         str_set(str,"");
  338.         if (fp) {
  339.         if (gimme == G_SCALAR) {
  340.             while (str_gets(str,fp,str->str_cur) != Nullch)
  341.             /*SUPPRESS 530*/
  342.             ;
  343.         }
  344.         else {
  345.             for (;;) {
  346.             if (++sp > stack->ary_max) {
  347.                 astore(stack, sp, Nullstr);
  348.                 st = stack->ary_array;
  349.             }
  350.             str = st[sp] = Str_new(56,80);
  351.             if (str_gets(str,fp,0) == Nullch) {
  352.                 sp--;
  353.                 break;
  354.             }
  355.             if (str->str_len - str->str_cur > 20) {
  356.                 str->str_len = str->str_cur+1;
  357.                 Renew(str->str_ptr, str->str_len, char);
  358.             }
  359.             str_2mortal(str);
  360.             }
  361.         }
  362.         statusvalue = mypclose(fp);
  363.         }
  364.         else
  365.         statusvalue = -1;
  366.  
  367.         if (gimme == G_SCALAR)
  368.         st[++sp] = str;
  369. #ifdef DEBUGGING
  370.         tmps = "BACK";
  371. #endif
  372.         break;
  373.     case A_WANTARRAY:
  374.         {
  375.         if (curcsv->wantarray == G_ARRAY)
  376.             st[++sp] = &str_yes;
  377.         else
  378.             st[++sp] = &str_no;
  379.         }
  380. #ifdef DEBUGGING
  381.         tmps = "WANTARRAY";
  382. #endif
  383.         break;
  384.     case A_INDREAD:
  385.         last_in_stab = stabent(str_get(STAB_STR(argptr.arg_stab)),TRUE);
  386.         old_rschar = rschar;
  387.         old_rslen = rslen;
  388.         goto do_read;
  389.     case A_GLOB:
  390.         argflags |= AF_POST;    /* enable newline chopping */
  391.         last_in_stab = argptr.arg_stab;
  392.         old_rschar = rschar;
  393.         old_rslen = rslen;
  394.         rslen = 1;
  395. #ifdef MSDOS
  396.         rschar = 0;
  397. #else
  398. #ifdef CSH
  399.         rschar = 0;
  400. #else
  401.         rschar = '\n';
  402. #endif    /* !CSH */
  403. #endif    /* !MSDOS */
  404.         goto do_read;
  405.     case A_READ:
  406.         last_in_stab = argptr.arg_stab;
  407.         old_rschar = rschar;
  408.         old_rslen = rslen;
  409.       do_read:
  410.         if (anum > 1)        /* assign to scalar */
  411.         gimme = G_SCALAR;    /* force context to scalar */
  412.         if (gimme == G_ARRAY)
  413.         str = Str_new(57,0);
  414.         ++sp;
  415.         fp = Nullfp;
  416.         if (stab_io(last_in_stab)) {
  417.         fp = stab_io(last_in_stab)->ifp;
  418.         if (!fp) {
  419.             if (stab_io(last_in_stab)->flags & IOF_ARGV) {
  420.             if (stab_io(last_in_stab)->flags & IOF_START) {
  421.                 stab_io(last_in_stab)->flags &= ~IOF_START;
  422.                 stab_io(last_in_stab)->lines = 0;
  423.                 if (alen(stab_array(last_in_stab)) < 0) {
  424.                 tmpstr = str_make("-",1); /* assume stdin */
  425.                 (void)apush(stab_array(last_in_stab), tmpstr);
  426.                 }
  427.             }
  428.             fp = nextargv(last_in_stab);
  429.             if (!fp) { /* Note: fp != stab_io(last_in_stab)->ifp */
  430.                 (void)do_close(last_in_stab,FALSE); /* now it does*/
  431.                 stab_io(last_in_stab)->flags |= IOF_START;
  432.             }
  433.             }
  434.             else if (argtype == A_GLOB) {
  435.             (void) interp(str,stab_val(last_in_stab),sp);
  436.             st = stack->ary_array;
  437.             tmpstr = Str_new(55,0);
  438. #ifdef MSDOS
  439.             str_set(tmpstr, "perlglob ");
  440.             str_scat(tmpstr,str);
  441.             str_cat(tmpstr," |");
  442. #else
  443. #ifdef CSH
  444.             str_nset(tmpstr,cshname,cshlen);
  445.             str_cat(tmpstr," -cf 'set nonomatch; glob ");
  446.             str_scat(tmpstr,str);
  447.             str_cat(tmpstr,"'|");
  448. #else
  449.             str_set(tmpstr, "echo ");
  450.             str_scat(tmpstr,str);
  451.             str_cat(tmpstr,
  452.               "|tr -s ' \t\f\r' '\\012\\012\\012\\012'|");
  453. #endif /* !CSH */
  454. #endif /* !MSDOS */
  455.             (void)do_open(last_in_stab,tmpstr->str_ptr,
  456.               tmpstr->str_cur);
  457.             fp = stab_io(last_in_stab)->ifp;
  458.             str_free(tmpstr);
  459.             }
  460.         }
  461.         }
  462.         if (!fp && dowarn)
  463.         warn("Read on closed filehandle <%s>",stab_name(last_in_stab));
  464.         when = str->str_len;    /* remember if already alloced */
  465.         if (!when)
  466.         Str_Grow(str,80);    /* try short-buffering it */
  467.       keepgoing:
  468.         if (!fp)
  469.         st[sp] = &str_undef;
  470.         else if (!str_gets(str,fp, optype == O_RCAT ? str->str_cur : 0)) {
  471.         clearerr(fp);
  472.         if (stab_io(last_in_stab)->flags & IOF_ARGV) {
  473.             fp = nextargv(last_in_stab);
  474.             if (fp)
  475.             goto keepgoing;
  476.             (void)do_close(last_in_stab,FALSE);
  477.             stab_io(last_in_stab)->flags |= IOF_START;
  478.         }
  479.         else if (argflags & AF_POST) {
  480.             (void)do_close(last_in_stab,FALSE);
  481.         }
  482.         st[sp] = &str_undef;
  483.         rschar = old_rschar;
  484.         rslen = old_rslen;
  485.         if (gimme == G_ARRAY) {
  486.             --sp;
  487.             str_2mortal(str);
  488.             goto array_return;
  489.         }
  490.         break;
  491.         }
  492.         else {
  493.         stab_io(last_in_stab)->lines++;
  494.         st[sp] = str;
  495. #ifdef TAINT
  496.         str->str_tainted = 1; /* Anything from the outside world...*/
  497. #endif
  498.         if (argflags & AF_POST) {
  499.             if (str->str_cur > 0)
  500.             str->str_cur--;
  501.             if (str->str_ptr[str->str_cur] == rschar)
  502.             str->str_ptr[str->str_cur] = '\0';
  503.             else
  504.             str->str_cur++;
  505.             for (tmps = str->str_ptr; *tmps; tmps++)
  506.             if (!isALPHA(*tmps) && !isDIGIT(*tmps) &&
  507.                 index("$&*(){}[]'\";\\|?<>~`",*tmps))
  508.                 break;
  509.             if (*tmps && stat(str->str_ptr,&statbuf) < 0)
  510.             goto keepgoing;        /* unmatched wildcard? */
  511.         }
  512.         if (gimme == G_ARRAY) {
  513.             if (str->str_len - str->str_cur > 20) {
  514.             str->str_len = str->str_cur+1;
  515.             Renew(str->str_ptr, str->str_len, char);
  516.             }
  517.             str_2mortal(str);
  518.             if (++sp > stack->ary_max) {
  519.             astore(stack, sp, Nullstr);
  520.             st = stack->ary_array;
  521.             }
  522.             str = Str_new(58,80);
  523.             goto keepgoing;
  524.         }
  525.         else if (!when && str->str_len - str->str_cur > 80) {
  526.             /* try to reclaim a bit of scalar space on 1st alloc */
  527.             if (str->str_cur < 60)
  528.             str->str_len = 80;
  529.             else
  530.             str->str_len = str->str_cur+40;    /* allow some slop */
  531.             Renew(str->str_ptr, str->str_len, char);
  532.         }
  533.         }
  534.         rschar = old_rschar;
  535.         rslen = old_rslen;
  536. #ifdef DEBUGGING
  537.         tmps = "READ";
  538. #endif
  539.         break;
  540.     }
  541. #ifdef DEBUGGING
  542.     if (debug & 8)
  543.         deb("%d.%s = '%s'\n",anum,tmps,str_peek(st[sp]));
  544. #endif
  545.     if (anum < 8)
  546.         arglast[anum] = sp;
  547.     }
  548.  
  549.     st += arglast[0];
  550. #ifdef SMALLSWITCHES
  551.     if (optype < O_CHOWN)
  552. #endif
  553.     switch (optype) {
  554.     case O_RCAT:
  555.     STABSET(str);
  556.     break;
  557.     case O_ITEM:
  558.     if (gimme == G_ARRAY)
  559.         goto array_return;
  560.     /* FALL THROUGH */
  561.     case O_SCALAR:
  562.     STR_SSET(str,st[1]);
  563.     STABSET(str);
  564.     break;
  565.     case O_ITEM2:
  566.     if (gimme == G_ARRAY)
  567.         goto array_return;
  568.     --anum;
  569.     STR_SSET(str,st[arglast[anum]-arglast[0]]);
  570.     STABSET(str);
  571.     break;
  572.     case O_ITEM3:
  573.     if (gimme == G_ARRAY)
  574.     goto array_return;
  575.     --anum;
  576.     STR_SSET(str,st[arglast[anum]-arglast[0]]);
  577.     STABSET(str);
  578.     break;
  579.     case O_CONCAT:
  580.     STR_SSET(str,st[1]);
  581.     str_scat(str,st[2]);
  582.     STABSET(str);
  583.     break;
  584.     case O_REPEAT:
  585.     if (gimme == G_ARRAY && arg[1].arg_flags & AF_ARYOK) {
  586.         sp = do_repeatary(arglast);
  587.         goto array_return;
  588.     }
  589.     STR_SSET(str,st[arglast[1] - arglast[0]]);
  590.     anum = (int)str_gnum(st[arglast[2] - arglast[0]]);
  591.     if (anum >= 1) {
  592.         tmpstr = Str_new(50, 0);
  593.         tmps = str_get(str);
  594.         str_nset(tmpstr,tmps,str->str_cur);
  595.         tmps = str_get(tmpstr);    /* force to be string */
  596.         STR_GROW(str, (anum * str->str_cur) + 1);
  597.         repeatcpy(str->str_ptr, tmps, tmpstr->str_cur, anum);
  598.         str->str_cur *= anum;
  599.         str->str_ptr[str->str_cur] = '\0';
  600.         str->str_nok = 0;
  601.         str_free(tmpstr);
  602.     }
  603.     else
  604.         str_sset(str,&str_no);
  605.     STABSET(str);
  606.     break;
  607.     case O_MATCH:
  608.     sp = do_match(str,arg,
  609.       gimme,arglast);
  610.     if (gimme == G_ARRAY)
  611.         goto array_return;
  612.     STABSET(str);
  613.     break;
  614.     case O_NMATCH:
  615.     sp = do_match(str,arg,
  616.       G_SCALAR,arglast);
  617.     str_sset(str, str_true(str) ? &str_no : &str_yes);
  618.     STABSET(str);
  619.     break;
  620.     case O_SUBST:
  621.     sp = do_subst(str,arg,arglast[0]);
  622.     goto array_return;
  623.     case O_NSUBST:
  624.     sp = do_subst(str,arg,arglast[0]);
  625.     str = arg->arg_ptr.arg_str;
  626.     str_set(str, str_true(str) ? No : Yes);
  627.     goto array_return;
  628.     case O_ASSIGN:
  629.     if (arg[1].arg_flags & AF_ARYOK) {
  630.         if (arg->arg_len == 1) {
  631.         arg->arg_type = O_LOCAL;
  632.         goto local;
  633.         }
  634.         else {
  635.         arg->arg_type = O_AASSIGN;
  636.         goto aassign;
  637.         }
  638.     }
  639.     else {
  640.         arg->arg_type = O_SASSIGN;
  641.         goto sassign;
  642.     }
  643.     case O_LOCAL:
  644.       local:
  645.     arglast[2] = arglast[1];    /* push a null array */
  646.     /* FALL THROUGH */
  647.     case O_AASSIGN:
  648.       aassign:
  649.     sp = do_assign(arg,
  650.       gimme,arglast);
  651.     goto array_return;
  652.     case O_SASSIGN:
  653.       sassign:
  654. #ifdef TAINT
  655.     if (tainted && !st[2]->str_tainted)
  656.         tainted = 0;
  657. #endif
  658.     STR_SSET(str, st[2]);
  659.     STABSET(str);
  660.     break;
  661.     case O_CHOP:
  662.     st -= arglast[0];
  663.     str = arg->arg_ptr.arg_str;
  664.     for (sp = arglast[0] + 1; sp <= arglast[1]; sp++)
  665.         do_chop(str,st[sp]);
  666.     st += arglast[0];
  667.     break;
  668.     case O_DEFINED:
  669.     if (arg[1].arg_type & A_DONT) {
  670.         sp = do_defined(str,arg,
  671.           gimme,arglast);
  672.         goto array_return;
  673.     }
  674.     else if (str->str_pok || str->str_nok)
  675.         goto say_yes;
  676.     goto say_no;
  677.     case O_UNDEF:
  678.     if (arg[1].arg_type & A_DONT) {
  679.         sp = do_undef(str,arg,
  680.           gimme,arglast);
  681.         goto array_return;
  682.     }
  683.     else if (str != stab_val(defstab)) {
  684.         if (str->str_len) {
  685.         if (str->str_state == SS_INCR)
  686.             Str_Grow(str,0);
  687.         Safefree(str->str_ptr);
  688.         str->str_ptr = Nullch;
  689.         str->str_len = 0;
  690.         }
  691.         str->str_pok = str->str_nok = 0;
  692.         STABSET(str);
  693.     }
  694.     goto say_undef;
  695.     case O_STUDY:
  696.     sp = do_study(str,arg,
  697.       gimme,arglast);
  698.     goto array_return;
  699.     case O_POW:
  700.     value = str_gnum(st[1]);
  701.     value = pow(value,str_gnum(st[2]));
  702.     goto donumset;
  703.     case O_MULTIPLY:
  704.     value = str_gnum(st[1]);
  705.     value *= str_gnum(st[2]);
  706.     goto donumset;
  707.     case O_DIVIDE:
  708.     if ((value = str_gnum(st[2])) == 0.0)
  709.         fatal("Illegal division by zero");
  710. #ifdef SLOPPYDIVIDE
  711.     /* insure that 20./5. == 4. */
  712.     {
  713.         double x;
  714.         int    k;
  715.         x =  str_gnum(st[1]);
  716.         if ((double)(int)x     == x &&
  717.         (double)(int)value == value &&
  718.         (k = (int)x/(int)value)*(int)value == (int)x) {
  719.         value = k;
  720.         } else {
  721.         value = x/value;
  722.         }
  723.     }
  724. #else
  725.     value = str_gnum(st[1]) / value;
  726. #endif
  727.     goto donumset;
  728.     case O_MODULO:
  729.     tmplong = (long) str_gnum(st[2]);
  730.         if (tmplong == 0L)
  731.             fatal("Illegal modulus zero");
  732.     when = (long)str_gnum(st[1]);
  733. #ifndef lint
  734.     if (when >= 0)
  735.         value = (double)(when % tmplong);
  736.     else
  737.         value = (double)(tmplong - ((-when - 1) % tmplong)) - 1;
  738. #endif
  739.     goto donumset;
  740.     case O_ADD:
  741.     value = str_gnum(st[1]);
  742.     value += str_gnum(st[2]);
  743.     goto donumset;
  744.     case O_SUBTRACT:
  745.     value = str_gnum(st[1]);
  746.     value -= str_gnum(st[2]);
  747.     goto donumset;
  748.     case O_LEFT_SHIFT:
  749.     value = str_gnum(st[1]);
  750.     anum = (int)str_gnum(st[2]);
  751. #ifndef lint
  752.     value = (double)(U_L(value) << anum);
  753. #endif
  754.     goto donumset;
  755.     case O_RIGHT_SHIFT:
  756.     value = str_gnum(st[1]);
  757.     anum = (int)str_gnum(st[2]);
  758. #ifndef lint
  759.     value = (double)(U_L(value) >> anum);
  760. #endif
  761.     goto donumset;
  762.     case O_LT:
  763.     value = str_gnum(st[1]);
  764.     value = (value < str_gnum(st[2])) ? 1.0 : 0.0;
  765.     goto donumset;
  766.     case O_GT:
  767.     value = str_gnum(st[1]);
  768.     value = (value > str_gnum(st[2])) ? 1.0 : 0.0;
  769.     goto donumset;
  770.     case O_LE:
  771.     value = str_gnum(st[1]);
  772.     value = (value <= str_gnum(st[2])) ? 1.0 : 0.0;
  773.     goto donumset;
  774.     case O_GE:
  775.     value = str_gnum(st[1]);
  776.     value = (value >= str_gnum(st[2])) ? 1.0 : 0.0;
  777.     goto donumset;
  778.     case O_EQ:
  779.     if (dowarn) {
  780.         if ((!st[1]->str_nok && !looks_like_number(st[1])) ||
  781.         (!st[2]->str_nok && !looks_like_number(st[2])) )
  782.         warn("Possible use of == on string value");
  783.     }
  784.     value = str_gnum(st[1]);
  785.     value = (value == str_gnum(st[2])) ? 1.0 : 0.0;
  786.     goto donumset;
  787.     case O_NE:
  788.     value = str_gnum(st[1]);
  789.     value = (value != str_gnum(st[2])) ? 1.0 : 0.0;
  790.     goto donumset;
  791.     case O_NCMP:
  792.     value = str_gnum(st[1]);
  793.     value -= str_gnum(st[2]);
  794.     if (value > 0.0)
  795.         value = 1.0;
  796.     else if (value < 0.0)
  797.         value = -1.0;
  798.     goto donumset;
  799.     case O_BIT_AND:
  800.     if (!sawvec || st[1]->str_nok || st[2]->str_nok) {
  801.         value = str_gnum(st[1]);
  802. #ifndef lint
  803.         value = (double)(U_L(value) & U_L(str_gnum(st[2])));
  804. #endif
  805.         goto donumset;
  806.     }
  807.     else
  808.         do_vop(optype,str,st[1],st[2]);
  809.     break;
  810.     case O_XOR:
  811.     if (!sawvec || st[1]->str_nok || st[2]->str_nok) {
  812.         value = str_gnum(st[1]);
  813. #ifndef lint
  814.         value = (double)(U_L(value) ^ U_L(str_gnum(st[2])));
  815. #endif
  816.         goto donumset;
  817.     }
  818.     else
  819.         do_vop(optype,str,st[1],st[2]);
  820.     break;
  821.     case O_BIT_OR:
  822.     if (!sawvec || st[1]->str_nok || st[2]->str_nok) {
  823.         value = str_gnum(st[1]);
  824. #ifndef lint
  825.         value = (double)(U_L(value) | U_L(str_gnum(st[2])));
  826. #endif
  827.         goto donumset;
  828.     }
  829.     else
  830.         do_vop(optype,str,st[1],st[2]);
  831.     break;
  832. /* use register in evaluating str_true() */
  833.     case O_AND:
  834.     if (str_true(st[1])) {
  835.         anum = 2;
  836.         optype = O_ITEM2;
  837.         argflags = arg[anum].arg_flags;
  838.         if (gimme == G_ARRAY)
  839.         argflags |= AF_ARYOK;
  840.         argtype = arg[anum].arg_type & A_MASK;
  841.         argptr = arg[anum].arg_ptr;
  842.         maxarg = anum = 1;
  843.         sp = arglast[0];
  844.         st -= sp;
  845.         goto re_eval;
  846.     }
  847.     else {
  848.         if (assigning) {
  849.         str_sset(str, st[1]);
  850.         STABSET(str);
  851.         }
  852.         else
  853.         str = st[1];
  854.         break;
  855.     }
  856.     case O_OR:
  857.     if (str_true(st[1])) {
  858.         if (assigning) {
  859.         str_sset(str, st[1]);
  860.         STABSET(str);
  861.         }
  862.         else
  863.         str = st[1];
  864.         break;
  865.     }
  866.     else {
  867.         anum = 2;
  868.         optype = O_ITEM2;
  869.         argflags = arg[anum].arg_flags;
  870.         if (gimme == G_ARRAY)
  871.         argflags |= AF_ARYOK;
  872.         argtype = arg[anum].arg_type & A_MASK;
  873.         argptr = arg[anum].arg_ptr;
  874.         maxarg = anum = 1;
  875.         sp = arglast[0];
  876.         st -= sp;
  877.         goto re_eval;
  878.     }
  879.     case O_COND_EXPR:
  880.     anum = (str_true(st[1]) ? 2 : 3);
  881.     optype = (anum == 2 ? O_ITEM2 : O_ITEM3);
  882.     argflags = arg[anum].arg_flags;
  883.     if (gimme == G_ARRAY)
  884.         argflags |= AF_ARYOK;
  885.     argtype = arg[anum].arg_type & A_MASK;
  886.     argptr = arg[anum].arg_ptr;
  887.     maxarg = anum = 1;
  888.     sp = arglast[0];
  889.     st -= sp;
  890.     goto re_eval;
  891.     case O_COMMA:
  892.     if (gimme == G_ARRAY)
  893.         goto array_return;
  894.     str = st[2];
  895.     break;
  896.     case O_NEGATE:
  897.     value = -str_gnum(st[1]);
  898.     goto donumset;
  899.     case O_NOT:
  900. #ifdef NOTNOT
  901.     { char xxx = str_true(st[1]); value = (double) !xxx; }
  902. #else
  903.     value = (double) !str_true(st[1]);
  904. #endif
  905.     goto donumset;
  906.     case O_COMPLEMENT:
  907.     if (!sawvec || st[1]->str_nok) {
  908. #ifndef lint
  909.         value = (double) ~U_L(str_gnum(st[1]));
  910. #endif
  911.         goto donumset;
  912.     }
  913.     else {
  914.         STR_SSET(str,st[1]);
  915.         tmps = str_get(str);
  916.         for (anum = str->str_cur; anum; anum--, tmps++)
  917.         *tmps = ~*tmps;
  918.     }
  919.     break;
  920.     case O_SELECT:
  921.     stab_fullname(str,defoutstab);
  922.     if (maxarg > 0) {
  923.         if ((arg[1].arg_type & A_MASK) == A_WORD)
  924.         defoutstab = arg[1].arg_ptr.arg_stab;
  925.         else
  926.         defoutstab = stabent(str_get(st[1]),TRUE);
  927.         if (!stab_io(defoutstab))
  928.         stab_io(defoutstab) = stio_new();
  929.         curoutstab = defoutstab;
  930.     }
  931.     STABSET(str);
  932.     break;
  933.     case O_WRITE:
  934.     if (maxarg == 0)
  935.         stab = defoutstab;
  936.     else if ((arg[1].arg_type & A_MASK) == A_WORD) {
  937.         if (!(stab = arg[1].arg_ptr.arg_stab))
  938.         stab = defoutstab;
  939.     }
  940.     else
  941.         stab = stabent(str_get(st[1]),TRUE);
  942.     if (!stab_io(stab)) {
  943.         str_set(str, No);
  944.         STABSET(str);
  945.         break;
  946.     }
  947.     curoutstab = stab;
  948.     fp = stab_io(stab)->ofp;
  949.     debarg = arg;
  950.     if (stab_io(stab)->fmt_stab)
  951.         form = stab_form(stab_io(stab)->fmt_stab);
  952.     else
  953.         form = stab_form(stab);
  954.     if (!form || !fp) {
  955.         if (dowarn) {
  956.         if (form)
  957.             warn("No format for filehandle");
  958.         else {
  959.             if (stab_io(stab)->ifp)
  960.             warn("Filehandle only opened for input");
  961.             else
  962.             warn("Write on closed filehandle");
  963.         }
  964.         }
  965.         str_set(str, No);
  966.         STABSET(str);
  967.         break;
  968.     }
  969.     format(&outrec,form,sp);
  970.     do_write(&outrec,stab,sp);
  971.     if (stab_io(stab)->flags & IOF_FLUSH)
  972.         (void)fflush(fp);
  973.     str_set(str, Yes);
  974.     STABSET(str);
  975.     break;
  976.     case O_DBMOPEN:
  977. #ifdef SOME_DBM
  978.     anum = arg[1].arg_type & A_MASK;
  979.     if (anum == A_WORD || anum == A_STAB)
  980.         stab = arg[1].arg_ptr.arg_stab;
  981.     else
  982.         stab = stabent(str_get(st[1]),TRUE);
  983.     if (st[3]->str_nok || st[3]->str_pok)
  984.         anum = (int)str_gnum(st[3]);
  985.     else
  986.         anum = -1;
  987.     value = (double)hdbmopen(stab_hash(stab),str_get(st[2]),anum);
  988.     goto donumset;
  989. #else
  990.     fatal("No dbm or ndbm on this machine");
  991. #endif
  992.     case O_DBMCLOSE:
  993. #ifdef SOME_DBM
  994.     if ((arg[1].arg_type & A_MASK) == A_WORD)
  995.         stab = arg[1].arg_ptr.arg_stab;
  996.     else
  997.         stab = stabent(str_get(st[1]),TRUE);
  998.     hdbmclose(stab_hash(stab));
  999.     goto say_yes;
  1000. #else
  1001.     fatal("No dbm or ndbm on this machine");
  1002. #endif
  1003.     case O_OPEN:
  1004.     if ((arg[1].arg_type & A_MASK) == A_WORD)
  1005.         stab = arg[1].arg_ptr.arg_stab;
  1006.     else
  1007.         stab = stabent(str_get(st[1]),TRUE);
  1008.     tmps = str_get(st[2]);
  1009.     if (do_open(stab,tmps,st[2]->str_cur)) {
  1010.         value = (double)forkprocess;
  1011.         stab_io(stab)->lines = 0;
  1012.         goto donumset;
  1013.     }
  1014.     else if (forkprocess == 0)        /* we are a new child */
  1015.         goto say_zero;
  1016.     else
  1017.         goto say_undef;
  1018.     /* break; */
  1019.     case O_TRANS:
  1020.     value = (double) do_trans(str,arg);
  1021.     str = arg->arg_ptr.arg_str;
  1022.     goto donumset;
  1023.     case O_NTRANS:
  1024.     str_set(arg->arg_ptr.arg_str, do_trans(str,arg) == 0 ? Yes : No);
  1025.     str = arg->arg_ptr.arg_str;
  1026.     break;
  1027.     case O_CLOSE:
  1028.     if (maxarg == 0)
  1029.         stab = defoutstab;
  1030.     else if ((arg[1].arg_type & A_MASK) == A_WORD)
  1031.         stab = arg[1].arg_ptr.arg_stab;
  1032.     else
  1033.         stab = stabent(str_get(st[1]),TRUE);
  1034.     str_set(str, do_close(stab,TRUE) ? Yes : No );
  1035.     STABSET(str);
  1036.     break;
  1037.     case O_EACH:
  1038.     sp = do_each(str,stab_hash(arg[1].arg_ptr.arg_stab),
  1039.       gimme,arglast);
  1040.     goto array_return;
  1041.     case O_VALUES:
  1042.     case O_KEYS:
  1043.     sp = do_kv(str,stab_hash(arg[1].arg_ptr.arg_stab), optype,
  1044.       gimme,arglast);
  1045.     goto array_return;
  1046.     case O_LARRAY:
  1047.     str->str_nok = str->str_pok = 0;
  1048.     str->str_u.str_stab = arg[1].arg_ptr.arg_stab;
  1049.     str->str_state = SS_ARY;
  1050.     break;
  1051.     case O_ARRAY:
  1052.     ary = stab_array(arg[1].arg_ptr.arg_stab);
  1053.     maxarg = ary->ary_fill + 1;
  1054.     if (gimme == G_ARRAY) { /* array wanted */
  1055.         sp = arglast[0];
  1056.         st -= sp;
  1057.         if (maxarg > 0 && sp + maxarg > stack->ary_max) {
  1058.         astore(stack,sp + maxarg, Nullstr);
  1059.         st = stack->ary_array;
  1060.         }
  1061.         st += sp;
  1062.         Copy(ary->ary_array, &st[1], maxarg, STR*);
  1063.         sp += maxarg;
  1064.         goto array_return;
  1065.     }
  1066.     else {
  1067.         value = (double)maxarg;
  1068.         goto donumset;
  1069.     }
  1070.     case O_AELEM:
  1071.     anum = ((int)str_gnum(st[2])) - arybase;
  1072.     str = afetch(stab_array(arg[1].arg_ptr.arg_stab),anum,FALSE);
  1073.     break;
  1074.     case O_DELETE:
  1075.     tmpstab = arg[1].arg_ptr.arg_stab;
  1076.     tmps = str_get(st[2]);
  1077.     str = hdelete(stab_hash(tmpstab),tmps,st[2]->str_cur);
  1078.     if (tmpstab == envstab)
  1079.         setenv(tmps,Nullch);
  1080.     if (!str)
  1081.         goto say_undef;
  1082.     break;
  1083.     case O_LHASH:
  1084.     str->str_nok = str->str_pok = 0;
  1085.     str->str_u.str_stab = arg[1].arg_ptr.arg_stab;
  1086.     str->str_state = SS_HASH;
  1087.     break;
  1088.     case O_HASH:
  1089.     if (gimme == G_ARRAY) { /* array wanted */
  1090.         sp = do_kv(str,stab_hash(arg[1].arg_ptr.arg_stab), optype,
  1091.         gimme,arglast);
  1092.         goto array_return;
  1093.     }
  1094.     else {
  1095.         tmpstab = arg[1].arg_ptr.arg_stab;
  1096.         if (!stab_hash(tmpstab)->tbl_fill)
  1097.         goto say_zero;
  1098.         sprintf(buf,"%d/%d",stab_hash(tmpstab)->tbl_fill,
  1099.         stab_hash(tmpstab)->tbl_max+1);
  1100.         str_set(str,buf);
  1101.     }
  1102.     break;
  1103.     case O_HELEM:
  1104.     tmpstab = arg[1].arg_ptr.arg_stab;
  1105.     tmps = str_get(st[2]);
  1106.     str = hfetch(stab_hash(tmpstab),tmps,st[2]->str_cur,FALSE);
  1107.     break;
  1108.     case O_LAELEM:
  1109.     anum = ((int)str_gnum(st[2])) - arybase;
  1110.     str = afetch(stab_array(arg[1].arg_ptr.arg_stab),anum,TRUE);
  1111.     if (!str || str == &str_undef)
  1112.         fatal("Assignment to non-creatable value, subscript %d",anum);
  1113.     break;
  1114.     case O_LHELEM:
  1115.     tmpstab = arg[1].arg_ptr.arg_stab;
  1116.     tmps = str_get(st[2]);
  1117.     anum = st[2]->str_cur;
  1118.     str = hfetch(stab_hash(tmpstab),tmps,anum,TRUE);
  1119.     if (!str || str == &str_undef)
  1120.         fatal("Assignment to non-creatable value, subscript \"%s\"",tmps);
  1121.     if (tmpstab == envstab)        /* heavy wizardry going on here */
  1122.         str_magic(str, tmpstab, 'E', tmps, anum);    /* str is now magic */
  1123.                     /* he threw the brick up into the air */
  1124.     else if (tmpstab == sigstab)
  1125.         str_magic(str, tmpstab, 'S', tmps, anum);
  1126. #ifdef SOME_DBM
  1127.     else if (stab_hash(tmpstab)->tbl_dbm)
  1128.         str_magic(str, tmpstab, 'D', tmps, anum);
  1129. #endif
  1130.     else if (tmpstab == DBline)
  1131.         str_magic(str, tmpstab, 'L', tmps, anum);
  1132.     break;
  1133.     case O_LSLICE:
  1134.     anum = 2;
  1135.     argtype = FALSE;
  1136.     goto do_slice_already;
  1137.     case O_ASLICE:
  1138.     anum = 1;
  1139.     argtype = FALSE;
  1140.     goto do_slice_already;
  1141.     case O_HSLICE:
  1142.     anum = 0;
  1143.     argtype = FALSE;
  1144.     goto do_slice_already;
  1145.     case O_LASLICE:
  1146.     anum = 1;
  1147.     argtype = TRUE;
  1148.     goto do_slice_already;
  1149.     case O_LHSLICE:
  1150.     anum = 0;
  1151.     argtype = TRUE;
  1152.       do_slice_already:
  1153.     sp = do_slice(arg[1].arg_ptr.arg_stab,str,anum,argtype,
  1154.         gimme,arglast);
  1155.     goto array_return;
  1156.     case O_SPLICE:
  1157.     sp = do_splice(stab_array(arg[1].arg_ptr.arg_stab),gimme,arglast);
  1158.     goto array_return;
  1159.     case O_PUSH:
  1160.     if (arglast[2] - arglast[1] != 1)
  1161.         str = do_push(stab_array(arg[1].arg_ptr.arg_stab),arglast);
  1162.     else {
  1163.         str = Str_new(51,0);        /* must copy the STR */
  1164.         str_sset(str,st[2]);
  1165.         (void)apush(stab_array(arg[1].arg_ptr.arg_stab),str);
  1166.     }
  1167.     break;
  1168.     case O_POP:
  1169.     str = apop(ary = stab_array(arg[1].arg_ptr.arg_stab));
  1170.     goto staticalization;
  1171.     case O_SHIFT:
  1172.     str = ashift(ary = stab_array(arg[1].arg_ptr.arg_stab));
  1173.       staticalization:
  1174.     if (!str)
  1175.         goto say_undef;
  1176.     if (ary->ary_flags & ARF_REAL)
  1177.         (void)str_2mortal(str);
  1178.     break;
  1179.     case O_UNPACK:
  1180.     sp = do_unpack(str,gimme,arglast);
  1181.     goto array_return;
  1182.     case O_SPLIT:
  1183.     value = str_gnum(st[3]);
  1184.     sp = do_split(str, arg[2].arg_ptr.arg_spat, (int)value,
  1185.       gimme,arglast);
  1186.     goto array_return;
  1187.     case O_LENGTH:
  1188.     if (maxarg < 1)
  1189.         value = (double)str_len(stab_val(defstab));
  1190.     else
  1191.         value = (double)str_len(st[1]);
  1192.     goto donumset;
  1193.     case O_SPRINTF:
  1194.     do_sprintf(str, sp-arglast[0], st+1);
  1195.     break;
  1196.     case O_SUBSTR:
  1197.     anum = ((int)str_gnum(st[2])) - arybase;    /* anum=where to start*/
  1198.     tmps = str_get(st[1]);        /* force conversion to string */
  1199.     /*SUPPRESS 560*/
  1200.     if (argtype = (str == st[1]))
  1201.         str = arg->arg_ptr.arg_str;
  1202.     if (anum < 0)
  1203.         anum += st[1]->str_cur + arybase;
  1204.     if (anum < 0 || anum > st[1]->str_cur)
  1205.         str_nset(str,"",0);
  1206.     else {
  1207.         optype = maxarg < 3 ? st[1]->str_cur : (int)str_gnum(st[3]);
  1208.         if (optype < 0)
  1209.         optype = 0;
  1210.         tmps += anum;
  1211.         anum = st[1]->str_cur - anum;    /* anum=how many bytes left*/
  1212.         if (anum > optype)
  1213.         anum = optype;
  1214.         str_nset(str, tmps, anum);
  1215.         if (argtype) {            /* it's an lvalue! */
  1216.         lstr = (struct lstring*)str;
  1217.         str->str_magic = st[1];
  1218.         st[1]->str_rare = 's';
  1219.         lstr->lstr_offset = tmps - str_get(st[1]); 
  1220.         lstr->lstr_len = anum; 
  1221.         }
  1222.     }
  1223.     break;
  1224.     case O_PACK:
  1225.     /*SUPPRESS 701*/
  1226.     (void)do_pack(str,arglast);
  1227.     break;
  1228.     case O_GREP:
  1229.     sp = do_grep(arg,str,gimme,arglast);
  1230.     goto array_return;
  1231.     case O_JOIN:
  1232.     do_join(str,arglast);
  1233.     break;
  1234.     case O_SLT:
  1235.     tmps = str_get(st[1]);
  1236.     value = (double) (str_cmp(st[1],st[2]) < 0);
  1237.     goto donumset;
  1238.     case O_SGT:
  1239.     tmps = str_get(st[1]);
  1240.     value = (double) (str_cmp(st[1],st[2]) > 0);
  1241.     goto donumset;
  1242.     case O_SLE:
  1243.     tmps = str_get(st[1]);
  1244.     value = (double) (str_cmp(st[1],st[2]) <= 0);
  1245.     goto donumset;
  1246.     case O_SGE:
  1247.     tmps = str_get(st[1]);
  1248.     value = (double) (str_cmp(st[1],st[2]) >= 0);
  1249.     goto donumset;
  1250.     case O_SEQ:
  1251.     tmps = str_get(st[1]);
  1252.     value = (double) str_eq(st[1],st[2]);
  1253.     goto donumset;
  1254.     case O_SNE:
  1255.     tmps = str_get(st[1]);
  1256.     value = (double) !str_eq(st[1],st[2]);
  1257.     goto donumset;
  1258.     case O_SCMP:
  1259.     tmps = str_get(st[1]);
  1260.     value = (double) str_cmp(st[1],st[2]);
  1261.     goto donumset;
  1262.     case O_SUBR:
  1263.     sp = do_subr(arg,gimme,arglast);
  1264.     st = stack->ary_array + arglast[0];        /* maybe realloced */
  1265.     goto array_return;
  1266.     case O_DBSUBR:
  1267.     sp = do_subr(arg,gimme,arglast);
  1268.     st = stack->ary_array + arglast[0];        /* maybe realloced */
  1269.     goto array_return;
  1270.     case O_CALLER:
  1271.     sp = do_caller(arg,maxarg,gimme,arglast);
  1272.     st = stack->ary_array + arglast[0];        /* maybe realloced */
  1273.     goto array_return;
  1274.     case O_SORT:
  1275.     sp = do_sort(str,arg,
  1276.       gimme,arglast);
  1277.     goto array_return;
  1278.     case O_REVERSE:
  1279.     if (gimme == G_ARRAY)
  1280.         sp = do_reverse(arglast);
  1281.     else
  1282.         sp = do_sreverse(str, arglast);
  1283.     goto array_return;
  1284.     case O_WARN:
  1285.     if (arglast[2] - arglast[1] != 1) {
  1286.         do_join(str,arglast);
  1287.         tmps = str_get(str);
  1288.     }
  1289.     else {
  1290.         str = st[2];
  1291.         tmps = str_get(st[2]);
  1292.     }
  1293.     if (!tmps || !*tmps)
  1294.         tmps = "Warning: something's wrong";
  1295.     warn("%s",tmps);
  1296.     goto say_yes;
  1297.     case O_DIE:
  1298.     if (arglast[2] - arglast[1] != 1) {
  1299.         do_join(str,arglast);
  1300.         tmps = str_get(str);
  1301.     }
  1302.     else {
  1303.         str = st[2];
  1304.         tmps = str_get(st[2]);
  1305.     }
  1306.     if (!tmps || !*tmps)
  1307.         tmps = "Died";
  1308.     fatal("%s",tmps);
  1309.     goto say_zero;
  1310.     case O_PRTF:
  1311.     case O_PRINT:
  1312.     if ((arg[1].arg_type & A_MASK) == A_WORD)
  1313.         stab = arg[1].arg_ptr.arg_stab;
  1314.     else
  1315.         stab = stabent(str_get(st[1]),TRUE);
  1316.     if (!stab)
  1317.         stab = defoutstab;
  1318.     if (!stab_io(stab)) {
  1319.         if (dowarn)
  1320.         warn("Filehandle never opened");
  1321.         goto say_zero;
  1322.     }
  1323.     if (!(fp = stab_io(stab)->ofp)) {
  1324.         if (dowarn)  {
  1325.         if (stab_io(stab)->ifp)
  1326.             warn("Filehandle opened only for input");
  1327.         else
  1328.             warn("Print on closed filehandle");
  1329.         }
  1330.         goto say_zero;
  1331.     }
  1332.     else {
  1333.         if (optype == O_PRTF || arglast[2] - arglast[1] != 1)
  1334.         value = (double)do_aprint(arg,fp,arglast);
  1335.         else {
  1336.         value = (double)do_print(st[2],fp);
  1337.         if (orslen && optype == O_PRINT)
  1338.             if (fwrite(ors, 1, orslen, fp) == 0)
  1339.             goto say_zero;
  1340.         }
  1341.         if (stab_io(stab)->flags & IOF_FLUSH)
  1342.         if (fflush(fp) == EOF)
  1343.             goto say_zero;
  1344.     }
  1345.     goto donumset;
  1346.     case O_CHDIR:
  1347.     if (maxarg < 1)
  1348.         tmps = Nullch;
  1349.     else
  1350.         tmps = str_get(st[1]);
  1351.     if (!tmps || !*tmps) {
  1352.         tmpstr = hfetch(stab_hash(envstab),"HOME",4,FALSE);
  1353.         tmps = str_get(tmpstr);
  1354.     }
  1355.     if (!tmps || !*tmps) {
  1356.         tmpstr = hfetch(stab_hash(envstab),"LOGDIR",6,FALSE);
  1357.         tmps = str_get(tmpstr);
  1358.     }
  1359. #ifdef TAINT
  1360.     taintproper("Insecure dependency in chdir");
  1361. #endif
  1362.     value = (double)(chdir(tmps) >= 0);
  1363.     goto donumset;
  1364.     case O_EXIT:
  1365.     if (maxarg < 1)
  1366.         anum = 0;
  1367.     else
  1368.         anum = (int)str_gnum(st[1]);
  1369.     exit(anum);
  1370.     goto say_zero;
  1371.     case O_RESET:
  1372.     if (maxarg < 1)
  1373.         tmps = "";
  1374.     else
  1375.         tmps = str_get(st[1]);
  1376.     str_reset(tmps,curcmd->c_stash);
  1377.     value = 1.0;
  1378.     goto donumset;
  1379.     case O_LIST:
  1380.     if (gimme == G_ARRAY)
  1381.         goto array_return;
  1382.     if (maxarg > 0)
  1383.         str = st[sp - arglast[0]];    /* unwanted list, return last item */
  1384.     else
  1385.         str = &str_undef;
  1386.     break;
  1387.     case O_EOF:
  1388.     if (maxarg <= 0)
  1389.         stab = last_in_stab;
  1390.     else if ((arg[1].arg_type & A_MASK) == A_WORD)
  1391.         stab = arg[1].arg_ptr.arg_stab;
  1392.     else
  1393.         stab = stabent(str_get(st[1]),TRUE);
  1394.     str_set(str, do_eof(stab) ? Yes : No);
  1395.     STABSET(str);
  1396.     break;
  1397.     case O_GETC:
  1398.     if (maxarg <= 0)
  1399.         stab = stdinstab;
  1400.     else if ((arg[1].arg_type & A_MASK) == A_WORD)
  1401.         stab = arg[1].arg_ptr.arg_stab;
  1402.     else
  1403.         stab = stabent(str_get(st[1]),TRUE);
  1404.     if (!stab)
  1405.         stab = argvstab;
  1406.     if (!stab || do_eof(stab)) /* make sure we have fp with something */
  1407.         goto say_undef;
  1408.     else {
  1409. #ifdef TAINT
  1410.         tainted = 1;
  1411. #endif
  1412.         str_set(str," ");
  1413.         *str->str_ptr = getc(stab_io(stab)->ifp); /* should never be EOF */
  1414.     }
  1415.     STABSET(str);
  1416.     break;
  1417.     case O_TELL:
  1418.     if (maxarg <= 0)
  1419.         stab = last_in_stab;
  1420.     else if ((arg[1].arg_type & A_MASK) == A_WORD)
  1421.         stab = arg[1].arg_ptr.arg_stab;
  1422.     else
  1423.         stab = stabent(str_get(st[1]),TRUE);
  1424. #ifndef lint
  1425.     value = (double)do_tell(stab);
  1426. #else
  1427.     (void)do_tell(stab);
  1428. #endif
  1429.     goto donumset;
  1430.     case O_RECV:
  1431.     case O_READ:
  1432.     case O_SYSREAD:
  1433.     if ((arg[1].arg_type & A_MASK) == A_WORD)
  1434.         stab = arg[1].arg_ptr.arg_stab;
  1435.     else
  1436.         stab = stabent(str_get(st[1]),TRUE);
  1437.     tmps = str_get(st[2]);
  1438.     anum = (int)str_gnum(st[3]);
  1439.     errno = 0;
  1440.     maxarg = sp - arglast[0];
  1441.     if (maxarg > 4)
  1442.         warn("Too many args on read");
  1443.     if (maxarg == 4)
  1444.         maxarg = (int)str_gnum(st[4]);
  1445.     else
  1446.         maxarg = 0;
  1447.     if (!stab_io(stab) || !stab_io(stab)->ifp)
  1448.         goto say_undef;
  1449. #ifdef HAS_SOCKET
  1450.     if (optype == O_RECV) {
  1451.         argtype = sizeof buf;
  1452.         STR_GROW(st[2], anum+1), (tmps = str_get(st[2]));  /* sneaky */
  1453.         anum = recvfrom(fileno(stab_io(stab)->ifp), tmps, anum, maxarg,
  1454.         buf, &argtype);
  1455.         if (anum >= 0) {
  1456.         st[2]->str_cur = anum;
  1457.         st[2]->str_ptr[anum] = '\0';
  1458.         str_nset(str,buf,argtype);
  1459.         }
  1460.         else
  1461.         str_sset(str,&str_undef);
  1462.         break;
  1463.     }
  1464. #else
  1465.     if (optype == O_RECV)
  1466.         goto badsock;
  1467. #endif
  1468.     STR_GROW(st[2], anum+maxarg+1), (tmps = str_get(st[2]));  /* sneaky */
  1469.     if (optype == O_SYSREAD) {
  1470.         anum = read(fileno(stab_io(stab)->ifp), tmps+maxarg, anum);
  1471.     }
  1472.     else
  1473. #ifdef HAS_SOCKET
  1474.     if (stab_io(stab)->type == 's') {
  1475.         argtype = sizeof buf;
  1476.         anum = recvfrom(fileno(stab_io(stab)->ifp), tmps+maxarg, anum, 0,
  1477.         buf, &argtype);
  1478.     }
  1479.     else
  1480. #endif
  1481.         anum = fread(tmps+maxarg, 1, anum, stab_io(stab)->ifp);
  1482.     if (anum < 0)
  1483.         goto say_undef;
  1484.     st[2]->str_cur = anum+maxarg;
  1485.     st[2]->str_ptr[anum+maxarg] = '\0';
  1486.     value = (double)anum;
  1487.     goto donumset;
  1488.     case O_SYSWRITE:
  1489.     case O_SEND:
  1490.     if ((arg[1].arg_type & A_MASK) == A_WORD)
  1491.         stab = arg[1].arg_ptr.arg_stab;
  1492.     else
  1493.         stab = stabent(str_get(st[1]),TRUE);
  1494.     tmps = str_get(st[2]);
  1495.     anum = (int)str_gnum(st[3]);
  1496.     errno = 0;
  1497.     stio = stab_io(stab);
  1498.     maxarg = sp - arglast[0];
  1499.     if (!stio || !stio->ifp) {
  1500.         anum = -1;
  1501.         if (dowarn) {
  1502.         if (optype == O_SYSWRITE)
  1503.             warn("Syswrite on closed filehandle");
  1504.         else
  1505.             warn("Send on closed socket");
  1506.         }
  1507.     }
  1508.     else if (optype == O_SYSWRITE) {
  1509.         if (maxarg > 4)
  1510.         warn("Too many args on syswrite");
  1511.         if (maxarg == 4)
  1512.         optype = (int)str_gnum(st[4]);
  1513.         else
  1514.         optype = 0;
  1515.         anum = write(fileno(stab_io(stab)->ifp), tmps+optype, anum);
  1516.     }
  1517. #ifdef HAS_SOCKET
  1518.     else if (maxarg >= 4) {
  1519.         if (maxarg > 4)
  1520.         warn("Too many args on send");
  1521.         tmps2 = str_get(st[4]);
  1522.         anum = sendto(fileno(stab_io(stab)->ifp), tmps, st[2]->str_cur,
  1523.           anum, tmps2, st[4]->str_cur);
  1524.     }
  1525.     else
  1526.         anum = send(fileno(stab_io(stab)->ifp), tmps, st[2]->str_cur, anum);
  1527. #else
  1528.     else
  1529.         goto badsock;
  1530. #endif
  1531.     if (anum < 0)
  1532.         goto say_undef;
  1533.     value = (double)anum;
  1534.     goto donumset;
  1535.     case O_SEEK:
  1536.     if ((arg[1].arg_type & A_MASK) == A_WORD)
  1537.         stab = arg[1].arg_ptr.arg_stab;
  1538.     else
  1539.         stab = stabent(str_get(st[1]),TRUE);
  1540.     value = str_gnum(st[2]);
  1541.     str_set(str, do_seek(stab,
  1542.       (long)value, (int)str_gnum(st[3]) ) ? Yes : No);
  1543.     STABSET(str);
  1544.     break;
  1545.     case O_RETURN:
  1546.     tmps = "_SUB_";        /* just fake up a "last _SUB_" */
  1547.     optype = O_LAST;
  1548.     if (curcsv && curcsv->wantarray == G_ARRAY) {
  1549.         lastretstr = Nullstr;
  1550.         lastspbase = arglast[1];
  1551.         lastsize = arglast[2] - arglast[1];
  1552.     }
  1553.     else
  1554.         lastretstr = str_mortal(st[arglast[2] - arglast[0]]);
  1555.     goto dopop;
  1556.     case O_REDO:
  1557.     case O_NEXT:
  1558.     case O_LAST:
  1559.     tmps = Nullch;
  1560.     if (maxarg > 0) {
  1561.         tmps = str_get(arg[1].arg_ptr.arg_str);
  1562.       dopop:
  1563.         while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
  1564.           strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
  1565. #ifdef DEBUGGING
  1566.         if (debug & 4) {
  1567.             deb("(Skipping label #%d %s)\n",loop_ptr,
  1568.             loop_stack[loop_ptr].loop_label);
  1569.         }
  1570. #endif
  1571.         loop_ptr--;
  1572.         }
  1573. #ifdef DEBUGGING
  1574.         if (debug & 4) {
  1575.         deb("(Found label #%d %s)\n",loop_ptr,
  1576.             loop_stack[loop_ptr].loop_label);
  1577.         }
  1578. #endif
  1579.     }
  1580.     if (loop_ptr < 0) {
  1581.         if (tmps && strEQ(tmps, "_SUB_"))
  1582.         fatal("Can't return outside a subroutine");
  1583.         fatal("Bad label: %s", maxarg > 0 ? tmps : "<null>");
  1584.     }
  1585.     if (!lastretstr && optype == O_LAST && lastsize) {
  1586.         st -= arglast[0];
  1587.         st += lastspbase + 1;
  1588.         optype = loop_stack[loop_ptr].loop_sp - lastspbase; /* negative */
  1589.         if (optype) {
  1590.         for (anum = lastsize; anum > 0; anum--,st++)
  1591.             st[optype] = str_mortal(st[0]);
  1592.         }
  1593.         longjmp(loop_stack[loop_ptr].loop_env, O_LAST);
  1594.     }
  1595.     longjmp(loop_stack[loop_ptr].loop_env, optype);
  1596.     case O_DUMP:
  1597.     case O_GOTO:/* shudder */
  1598.     goto_targ = str_get(arg[1].arg_ptr.arg_str);
  1599.     if (!*goto_targ)
  1600.         goto_targ = Nullch;        /* just restart from top */
  1601.     if (optype == O_DUMP) {
  1602.         do_undump = 1;
  1603.         my_unexec();
  1604.     }
  1605.     longjmp(top_env, 1);
  1606.     case O_INDEX:
  1607.     tmps = str_get(st[1]);
  1608.     if (maxarg < 3)
  1609.         anum = 0;
  1610.     else {
  1611.         anum = (int) str_gnum(st[3]) - arybase;
  1612.         if (anum < 0)
  1613.         anum = 0;
  1614.         else if (anum > st[1]->str_cur)
  1615.         anum = st[1]->str_cur;
  1616.     }
  1617. #ifndef lint
  1618.     if (!(tmps2 = fbminstr((unsigned char*)tmps + anum,
  1619.       (unsigned char*)tmps + st[1]->str_cur, st[2])))
  1620. #else
  1621.     if (tmps2 = fbminstr(Null(unsigned char*),Null(unsigned char*),Nullstr))
  1622. #endif
  1623.         value = (double)(-1 + arybase);
  1624.     else
  1625.         value = (double)(tmps2 - tmps + arybase);
  1626.     goto donumset;
  1627.     case O_RINDEX:
  1628.     tmps = str_get(st[1]);
  1629.     tmps2 = str_get(st[2]);
  1630.     if (maxarg < 3)
  1631.         anum = st[1]->str_cur;
  1632.     else {
  1633.         anum = (int) str_gnum(st[3]) - arybase + st[2]->str_cur;
  1634.         if (anum < 0)
  1635.         anum = 0;
  1636.         else if (anum > st[1]->str_cur)
  1637.         anum = st[1]->str_cur;
  1638.     }
  1639. #ifndef lint
  1640.     if (!(tmps2 = rninstr(tmps,  tmps  + anum,
  1641.                   tmps2, tmps2 + st[2]->str_cur)))
  1642. #else
  1643.     if (tmps2 = rninstr(Nullch,Nullch,Nullch,Nullch))
  1644. #endif
  1645.         value = (double)(-1 + arybase);
  1646.     else
  1647.         value = (double)(tmps2 - tmps + arybase);
  1648.     goto donumset;
  1649.     case O_TIME:
  1650. #ifndef lint
  1651.     value = (double) time(Null(long*));
  1652. #endif
  1653.     goto donumset;
  1654.     case O_TMS:
  1655.     sp = do_tms(str,gimme,arglast);
  1656.     goto array_return;
  1657.     case O_LOCALTIME:
  1658.     if (maxarg < 1)
  1659.         (void)time(&when);
  1660.     else
  1661.         when = (long)str_gnum(st[1]);
  1662.     sp = do_time(str,localtime(&when),
  1663.       gimme,arglast);
  1664.     goto array_return;
  1665.     case O_GMTIME:
  1666.     if (maxarg < 1)
  1667.         (void)time(&when);
  1668.     else
  1669.         when = (long)str_gnum(st[1]);
  1670.     sp = do_time(str,gmtime(&when),
  1671.       gimme,arglast);
  1672.     goto array_return;
  1673.     case O_TRUNCATE:
  1674.     sp = do_truncate(str,arg,
  1675.       gimme,arglast);
  1676.     goto array_return;
  1677.     case O_LSTAT:
  1678.     case O_STAT:
  1679.     sp = do_stat(str,arg,
  1680.       gimme,arglast);
  1681.     goto array_return;
  1682.     case O_CRYPT:
  1683. #ifdef HAS_CRYPT
  1684.     tmps = str_get(st[1]);
  1685. #ifdef FCRYPT
  1686.     str_set(str,fcrypt(tmps,str_get(st[2])));
  1687. #else
  1688.     str_set(str,crypt(tmps,str_get(st[2])));
  1689. #endif
  1690. #else
  1691.     fatal(
  1692.       "The crypt() function is unimplemented due to excessive paranoia.");
  1693. #endif
  1694.     break;
  1695.     case O_ATAN2:
  1696.     value = str_gnum(st[1]);
  1697.     value = atan2(value,str_gnum(st[2]));
  1698.     goto donumset;
  1699.     case O_SIN:
  1700.     if (maxarg < 1)
  1701.         value = str_gnum(stab_val(defstab));
  1702.     else
  1703.         value = str_gnum(st[1]);
  1704.     value = sin(value);
  1705.     goto donumset;
  1706.     case O_COS:
  1707.     if (maxarg < 1)
  1708.         value = str_gnum(stab_val(defstab));
  1709.     else
  1710.         value = str_gnum(st[1]);
  1711.     value = cos(value);
  1712.     goto donumset;
  1713.     case O_RAND:
  1714.     if (maxarg < 1)
  1715.         value = 1.0;
  1716.     else
  1717.         value = str_gnum(st[1]);
  1718.     if (value == 0.0)
  1719.         value = 1.0;
  1720. #if RANDBITS == 31
  1721.     value = rand() * value / 2147483648.0;
  1722. #else
  1723. #if RANDBITS == 16
  1724.     value = rand() * value / 65536.0;
  1725. #else
  1726. #if RANDBITS == 15
  1727.     value = rand() * value / 32768.0;
  1728. #else
  1729.     value = rand() * value / (double)(((unsigned long)1) << RANDBITS);
  1730. #endif
  1731. #endif
  1732. #endif
  1733.     goto donumset;
  1734.     case O_SRAND:
  1735.     if (maxarg < 1) {
  1736.         (void)time(&when);
  1737.         anum = when;
  1738.     }
  1739.     else
  1740.         anum = (int)str_gnum(st[1]);
  1741.     (void)srand(anum);
  1742.     goto say_yes;
  1743.     case O_EXP:
  1744.     if (maxarg < 1)
  1745.         value = str_gnum(stab_val(defstab));
  1746.     else
  1747.         value = str_gnum(st[1]);
  1748.     value = exp(value);
  1749.     goto donumset;
  1750.     case O_LOG:
  1751.     if (maxarg < 1)
  1752.         value = str_gnum(stab_val(defstab));
  1753.     else
  1754.         value = str_gnum(st[1]);
  1755.     if (value <= 0.0)
  1756.         fatal("Can't take log of %g\n", value);
  1757.     value = log(value);
  1758.     goto donumset;
  1759.     case O_SQRT:
  1760.     if (maxarg < 1)
  1761.         value = str_gnum(stab_val(defstab));
  1762.     else
  1763.         value = str_gnum(st[1]);
  1764.     if (value < 0.0)
  1765.         fatal("Can't take sqrt of %g\n", value);
  1766.     value = sqrt(value);
  1767.     goto donumset;
  1768.     case O_INT:
  1769.     if (maxarg < 1)
  1770.         value = str_gnum(stab_val(defstab));
  1771.     else
  1772.         value = str_gnum(st[1]);
  1773.     if (value >= 0.0)
  1774.         (void)modf(value,&value);
  1775.     else {
  1776.         (void)modf(-value,&value);
  1777.         value = -value;
  1778.     }
  1779.     goto donumset;
  1780.     case O_ORD:
  1781.     if (maxarg < 1)
  1782.         tmps = str_get(stab_val(defstab));
  1783.     else
  1784.         tmps = str_get(st[1]);
  1785. #ifndef I286
  1786.     value = (double) (*tmps & 255);
  1787. #else
  1788.     anum = (int) *tmps;
  1789.     value = (double) (anum & 255);
  1790. #endif
  1791.     goto donumset;
  1792.     case O_ALARM:
  1793. #ifdef HAS_ALARM
  1794.     if (maxarg < 1)
  1795.         tmps = str_get(stab_val(defstab));
  1796.     else
  1797.         tmps = str_get(st[1]);
  1798.     if (!tmps)
  1799.         tmps = "0";
  1800.     anum = alarm((unsigned int)atoi(tmps));
  1801.     if (anum < 0)
  1802.         goto say_undef;
  1803.     value = (double)anum;
  1804.     goto donumset;
  1805. #else
  1806.     fatal("Unsupported function alarm");
  1807.     break;
  1808. #endif
  1809.     case O_SLEEP:
  1810.     if (maxarg < 1)
  1811.         tmps = Nullch;
  1812.     else
  1813.         tmps = str_get(st[1]);
  1814.     (void)time(&when);
  1815.     if (!tmps || !*tmps)
  1816.         sleep((32767<<16)+32767);
  1817.     else
  1818.         sleep((unsigned int)atoi(tmps));
  1819. #ifndef lint
  1820.     value = (double)when;
  1821.     (void)time(&when);
  1822.     value = ((double)when) - value;
  1823. #endif
  1824.     goto donumset;
  1825.     case O_RANGE:
  1826.     sp = do_range(gimme,arglast);
  1827.     goto array_return;
  1828.     case O_F_OR_R:
  1829.     if (gimme == G_ARRAY) {        /* it's a range */
  1830.         /* can we optimize to constant array? */
  1831.         if ((arg[1].arg_type & A_MASK) == A_SINGLE &&
  1832.           (arg[2].arg_type & A_MASK) == A_SINGLE) {
  1833.         st[2] = arg[2].arg_ptr.arg_str;
  1834.         sp = do_range(gimme,arglast);
  1835.         st = stack->ary_array;
  1836.         maxarg = sp - arglast[0];
  1837.         str_free(arg[1].arg_ptr.arg_str);
  1838.         arg[1].arg_ptr.arg_str = Nullstr;
  1839.         str_free(arg[2].arg_ptr.arg_str);
  1840.         arg[2].arg_ptr.arg_str = Nullstr;
  1841.         arg->arg_type = O_ARRAY;
  1842.         arg[1].arg_type = A_STAB|A_DONT;
  1843.         arg->arg_len = 1;
  1844.         stab = arg[1].arg_ptr.arg_stab = aadd(genstab());
  1845.         ary = stab_array(stab);
  1846.         afill(ary,maxarg - 1);
  1847.         anum = maxarg;
  1848.         st += arglast[0]+1;
  1849.         while (maxarg-- > 0)
  1850.             ary->ary_array[maxarg] = str_smake(st[maxarg]);
  1851.         st -= arglast[0]+1;
  1852.         goto array_return;
  1853.         }
  1854.         arg->arg_type = optype = O_RANGE;
  1855.         maxarg = arg->arg_len = 2;
  1856.         anum = 2;
  1857.         arg[anum].arg_flags &= ~AF_ARYOK;
  1858.         argflags = arg[anum].arg_flags;
  1859.         argtype = arg[anum].arg_type & A_MASK;
  1860.         arg[anum].arg_type = argtype;
  1861.         argptr = arg[anum].arg_ptr;
  1862.         sp = arglast[0];
  1863.         st -= sp;
  1864.         sp++;
  1865.         goto re_eval;
  1866.     }
  1867.     arg->arg_type = O_FLIP;
  1868.     /* FALL THROUGH */
  1869.     case O_FLIP:
  1870.     if ((arg[1].arg_type & A_MASK) == A_SINGLE ?
  1871.       last_in_stab && (int)str_gnum(st[1]) == stab_io(last_in_stab)->lines
  1872.       :
  1873.       str_true(st[1]) ) {
  1874.         str_numset(str,0.0);
  1875.         anum = 2;
  1876.         arg->arg_type = optype = O_FLOP;
  1877.         arg[2].arg_type &= ~A_DONT;
  1878.         arg[1].arg_type |= A_DONT;
  1879.         argflags = arg[2].arg_flags;
  1880.         argtype = arg[2].arg_type & A_MASK;
  1881.         argptr = arg[2].arg_ptr;
  1882.         sp = arglast[0];
  1883.         st -= sp++;
  1884.         goto re_eval;
  1885.     }
  1886.     str_set(str,"");
  1887.     break;
  1888.     case O_FLOP:
  1889.     str_inc(str);
  1890.     if ((arg[2].arg_type & A_MASK) == A_SINGLE ?
  1891.       last_in_stab && (int)str_gnum(st[2]) == stab_io(last_in_stab)->lines
  1892.       :
  1893.       str_true(st[2]) ) {
  1894.         arg->arg_type = O_FLIP;
  1895.         arg[1].arg_type &= ~A_DONT;
  1896.         arg[2].arg_type |= A_DONT;
  1897.         str_cat(str,"E0");
  1898.     }
  1899.     break;
  1900.     case O_FORK:
  1901. #ifdef HAS_FORK
  1902.     anum = fork();
  1903.     if (anum < 0)
  1904.         goto say_undef;
  1905.     if (!anum) {
  1906.         /*SUPPRESS 560*/
  1907.         if (tmpstab = stabent("$",allstabs))
  1908.         str_numset(STAB_STR(tmpstab),(double)getpid());
  1909.         hclear(pidstatus, FALSE);    /* no kids, so don't wait for 'em */
  1910.     }
  1911.     value = (double)anum;
  1912.     goto donumset;
  1913. #else
  1914.     fatal("Unsupported function fork");
  1915.     break;
  1916. #endif
  1917.     case O_WAIT:
  1918. #ifdef HAS_WAIT
  1919. #ifndef lint
  1920.     anum = wait(&argflags);
  1921.     if (anum > 0)
  1922.         pidgone(anum,argflags);
  1923.     value = (double)anum;
  1924. #endif
  1925.     statusvalue = (unsigned short)argflags;
  1926.     goto donumset;
  1927. #else
  1928.     fatal("Unsupported function wait");
  1929.     break;
  1930. #endif
  1931.     case O_WAITPID:
  1932. #ifdef HAS_WAIT
  1933. #ifndef lint
  1934.     anum = (int)str_gnum(st[1]);
  1935.     optype = (int)str_gnum(st[2]);
  1936.     anum = wait4pid(anum, &argflags,optype);
  1937.     value = (double)anum;
  1938. #endif
  1939.     statusvalue = (unsigned short)argflags;
  1940.     goto donumset;
  1941. #else
  1942.     fatal("Unsupported function wait");
  1943.     break;
  1944. #endif
  1945.     case O_SYSTEM:
  1946. #ifdef HAS_FORK
  1947. #ifdef TAINT
  1948.     if (arglast[2] - arglast[1] == 1) {
  1949.         taintenv();
  1950.         tainted |= st[2]->str_tainted;
  1951.         taintproper("Insecure dependency in system");
  1952.     }
  1953. #endif
  1954.     while ((anum = vfork()) == -1) {
  1955.         if (errno != EAGAIN) {
  1956.         value = -1.0;
  1957.         goto donumset;
  1958.         }
  1959.         sleep(5);
  1960.     }
  1961.     if (anum > 0) {
  1962. #ifndef lint
  1963.         ihand = signal(SIGINT, SIG_IGN);
  1964.         qhand = signal(SIGQUIT, SIG_IGN);
  1965.         argtype = wait4pid(anum, &argflags, 0);
  1966. #else
  1967.         ihand = qhand = 0;
  1968. #endif
  1969.         (void)signal(SIGINT, ihand);
  1970.         (void)signal(SIGQUIT, qhand);
  1971.         statusvalue = (unsigned short)argflags;
  1972.         if (argtype < 0)
  1973.         value = -1.0;
  1974.         else {
  1975.         value = (double)((unsigned int)argflags & 0xffff);
  1976.         }
  1977.         do_execfree();    /* free any memory child malloced on vfork */
  1978.         goto donumset;
  1979.     }
  1980.     if ((arg[1].arg_type & A_MASK) == A_STAB)
  1981.         value = (double)do_aexec(st[1],arglast);
  1982.     else if (arglast[2] - arglast[1] != 1)
  1983.         value = (double)do_aexec(Nullstr,arglast);
  1984.     else {
  1985.         value = (double)do_exec(str_get(str_mortal(st[2])));
  1986.     }
  1987.     _exit(-1);
  1988. #else /* ! FORK */
  1989.     if ((arg[1].arg_type & A_MASK) == A_STAB)
  1990.         value = (double)do_aspawn(st[1],arglast);
  1991.     else if (arglast[2] - arglast[1] != 1)
  1992.         value = (double)do_aspawn(Nullstr,arglast);
  1993.     else {
  1994.         value = (double)do_spawn(str_get(str_mortal(st[2])));
  1995.     }
  1996.     goto donumset;
  1997. #endif /* FORK */
  1998.     case O_EXEC_OP:
  1999.     if ((arg[1].arg_type & A_MASK) == A_STAB)
  2000.         value = (double)do_aexec(st[1],arglast);
  2001.     else if (arglast[2] - arglast[1] != 1)
  2002.         value = (double)do_aexec(Nullstr,arglast);
  2003.     else {
  2004. #ifdef TAINT
  2005.         taintenv();
  2006.         tainted |= st[2]->str_tainted;
  2007.         taintproper("Insecure dependency in exec");
  2008. #endif
  2009.         value = (double)do_exec(str_get(str_mortal(st[2])));
  2010.     }
  2011.     goto donumset;
  2012.     case O_HEX:
  2013.     if (maxarg < 1)
  2014.         tmps = str_get(stab_val(defstab));
  2015.     else
  2016.         tmps = str_get(st[1]);
  2017.     value = (double)scanhex(tmps, 99, &argtype);
  2018.     goto donumset;
  2019.  
  2020.     case O_OCT:
  2021.     if (maxarg < 1)
  2022.         tmps = str_get(stab_val(defstab));
  2023.     else
  2024.         tmps = str_get(st[1]);
  2025.     while (*tmps && (isSPACE(*tmps) || *tmps == '0'))
  2026.         tmps++;
  2027.     if (*tmps == 'x')
  2028.         value = (double)scanhex(++tmps, 99, &argtype);
  2029.     else
  2030.         value = (double)scanoct(tmps, 99, &argtype);
  2031.     goto donumset;
  2032.  
  2033. /* These common exits are hidden here in the middle of the switches for the
  2034.    benefit of those machines with limited branch addressing.  Sigh.  */
  2035.  
  2036. array_return:
  2037. #ifdef DEBUGGING
  2038.     if (debug) {
  2039.     dlevel--;
  2040.     if (debug & 8) {
  2041.         anum = sp - arglast[0];
  2042.         switch (anum) {
  2043.         case 0:
  2044.         deb("%s RETURNS ()\n",opname[optype]);
  2045.         break;
  2046.         case 1:
  2047.         deb("%s RETURNS (\"%s\")\n",opname[optype],
  2048.             st[1] ? str_get(st[1]) : "");
  2049.         break;
  2050.         default:
  2051.         tmps = st[1] ? str_get(st[1]) : "";
  2052.         deb("%s RETURNS %d ARGS (\"%s\",%s\"%s\")\n",opname[optype],
  2053.           anum,tmps,anum==2?"":"...,",
  2054.             st[anum] ? str_get(st[anum]) : "");
  2055.         break;
  2056.         }
  2057.     }
  2058.     }
  2059. #endif
  2060.     return sp;
  2061.  
  2062. say_yes:
  2063.     str = &str_yes;
  2064.     goto normal_return;
  2065.  
  2066. say_no:
  2067.     str = &str_no;
  2068.     goto normal_return;
  2069.  
  2070. say_undef:
  2071.     str = &str_undef;
  2072.     goto normal_return;
  2073.  
  2074. say_zero:
  2075.     value = 0.0;
  2076.     /* FALL THROUGH */
  2077.  
  2078. donumset:
  2079.     str_numset(str,value);
  2080.     STABSET(str);
  2081.     st[1] = str;
  2082. #ifdef DEBUGGING
  2083.     if (debug) {
  2084.     dlevel--;
  2085.     if (debug & 8)
  2086.         deb("%s RETURNS \"%f\"\n",opname[optype],value);
  2087.     }
  2088. #endif
  2089.     return arglast[0] + 1;
  2090. #ifdef SMALLSWITCHES
  2091.     }
  2092.     else
  2093.     switch (optype) {
  2094. #endif
  2095.     case O_CHOWN:
  2096. #ifdef HAS_CHOWN
  2097.     value = (double)apply(optype,arglast);
  2098.     goto donumset;
  2099. #else
  2100.     fatal("Unsupported function chown");
  2101.     break;
  2102. #endif
  2103.     case O_KILL:
  2104. #ifdef HAS_KILL
  2105.     value = (double)apply(optype,arglast);
  2106.     goto donumset;
  2107. #else
  2108.     fatal("Unsupported function kill");
  2109.     break;
  2110. #endif
  2111.     case O_UNLINK:
  2112.     case O_CHMOD:
  2113.     case O_UTIME:
  2114.     value = (double)apply(optype,arglast);
  2115.     goto donumset;
  2116.     case O_UMASK:
  2117. #ifdef HAS_UMASK
  2118.     if (maxarg < 1) {
  2119.         anum = umask(0);
  2120.         (void)umask(anum);
  2121.     }
  2122.     else
  2123.         anum = umask((int)str_gnum(st[1]));
  2124.     value = (double)anum;
  2125. #ifdef TAINT
  2126.     taintproper("Insecure dependency in umask");
  2127. #endif
  2128.     goto donumset;
  2129. #else
  2130.     fatal("Unsupported function umask");
  2131.     break;
  2132. #endif
  2133. #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
  2134.     case O_MSGGET:
  2135.     case O_SHMGET:
  2136.     case O_SEMGET:
  2137.     if ((anum = do_ipcget(optype, arglast)) == -1)
  2138.         goto say_undef;
  2139.     value = (double)anum;
  2140.     goto donumset;
  2141.     case O_MSGCTL:
  2142.     case O_SHMCTL:
  2143.     case O_SEMCTL:
  2144.     anum = do_ipcctl(optype, arglast);
  2145.     if (anum == -1)
  2146.         goto say_undef;
  2147.     if (anum != 0) {
  2148.         value = (double)anum;
  2149.         goto donumset;
  2150.     }
  2151.     str_set(str,"0 but true");
  2152.     STABSET(str);
  2153.     break;
  2154.     case O_MSGSND:
  2155.     value = (double)(do_msgsnd(arglast) >= 0);
  2156.     goto donumset;
  2157.     case O_MSGRCV:
  2158.     value = (double)(do_msgrcv(arglast) >= 0);
  2159.     goto donumset;
  2160.     case O_SEMOP:
  2161.     value = (double)(do_semop(arglast) >= 0);
  2162.     goto donumset;
  2163.     case O_SHMREAD:
  2164.     case O_SHMWRITE:
  2165.     value = (double)(do_shmio(optype, arglast) >= 0);
  2166.     goto donumset;
  2167. #else /* not SYSVIPC */
  2168.     case O_MSGGET:
  2169.     case O_MSGCTL:
  2170.     case O_MSGSND:
  2171.     case O_MSGRCV:
  2172.     case O_SEMGET:
  2173.     case O_SEMCTL:
  2174.     case O_SEMOP:
  2175.     case O_SHMGET:
  2176.     case O_SHMCTL:
  2177.     case O_SHMREAD:
  2178.     case O_SHMWRITE:
  2179.     fatal("System V IPC is not implemented on this machine");
  2180. #endif /* not SYSVIPC */
  2181.     case O_RENAME:
  2182.     tmps = str_get(st[1]);
  2183.     tmps2 = str_get(st[2]);
  2184. #ifdef TAINT
  2185.     taintproper("Insecure dependency in rename");
  2186. #endif
  2187. #ifdef HAS_RENAME
  2188.     value = (double)(rename(tmps,tmps2) >= 0);
  2189. #else
  2190.     if (same_dirent(tmps2, tmps))    /* can always rename to same name */
  2191.         anum = 1;
  2192.     else {
  2193.         if (euid || stat(tmps2,&statbuf) < 0 || !S_ISDIR(statbuf.st_mode))
  2194.         (void)UNLINK(tmps2);
  2195.         if (!(anum = link(tmps,tmps2)))
  2196.         anum = UNLINK(tmps);
  2197.     }
  2198.     value = (double)(anum >= 0);
  2199. #endif
  2200.     goto donumset;
  2201.     case O_LINK:
  2202. #ifdef HAS_LINK
  2203.     tmps = str_get(st[1]);
  2204.     tmps2 = str_get(st[2]);
  2205. #ifdef TAINT
  2206.     taintproper("Insecure dependency in link");
  2207. #endif
  2208.     value = (double)(link(tmps,tmps2) >= 0);
  2209.     goto donumset;
  2210. #else
  2211.     fatal("Unsupported function link");
  2212.     break;
  2213. #endif
  2214.     case O_MKDIR:
  2215.     tmps = str_get(st[1]);
  2216.     anum = (int)str_gnum(st[2]);
  2217. #ifdef TAINT
  2218.     taintproper("Insecure dependency in mkdir");
  2219. #endif
  2220. #ifdef HAS_MKDIR
  2221.     value = (double)(mkdir(tmps,anum) >= 0);
  2222.     goto donumset;
  2223. #else
  2224.     (void)strcpy(buf,"mkdir ");
  2225. #endif
  2226. #if !defined(HAS_MKDIR) || !defined(HAS_RMDIR)
  2227.       one_liner:
  2228.     for (tmps2 = buf+6; *tmps; ) {
  2229.         *tmps2++ = '\\';
  2230.         *tmps2++ = *tmps++;
  2231.     }
  2232.     (void)strcpy(tmps2," 2>&1");
  2233.     rsfp = mypopen(buf,"r");
  2234.     if (rsfp) {
  2235.         *buf = '\0';
  2236.         tmps2 = fgets(buf,sizeof buf,rsfp);
  2237.         (void)mypclose(rsfp);
  2238.         if (tmps2 != Nullch) {
  2239.         for (errno = 1; errno < sys_nerr; errno++) {
  2240.             if (instr(buf,sys_errlist[errno]))    /* you don't see this */
  2241.             goto say_zero;
  2242.         }
  2243.         errno = 0;
  2244. #ifndef EACCES
  2245. #define EACCES EPERM
  2246. #endif
  2247.         if (instr(buf,"cannot make"))
  2248.             errno = EEXIST;
  2249.         else if (instr(buf,"existing file"))
  2250.             errno = EEXIST;
  2251.         else if (instr(buf,"ile exists"))
  2252.             errno = EEXIST;
  2253.         else if (instr(buf,"non-exist"))
  2254.             errno = ENOENT;
  2255.         else if (instr(buf,"does not exist"))
  2256.             errno = ENOENT;
  2257.         else if (instr(buf,"not empty"))
  2258.             errno = EBUSY;
  2259.         else if (instr(buf,"cannot access"))
  2260.             errno = EACCES;
  2261.         else
  2262.             errno = EPERM;
  2263.         goto say_zero;
  2264.         }
  2265.         else {    /* some mkdirs return no failure indication */
  2266.         tmps = str_get(st[1]);
  2267.         anum = (stat(tmps,&statbuf) >= 0);
  2268.         if (optype == O_RMDIR)
  2269.             anum = !anum;
  2270.         if (anum)
  2271.             errno = 0;
  2272.         else
  2273.             errno = EACCES;    /* a guess */
  2274.         value = (double)anum;
  2275.         }
  2276.         goto donumset;
  2277.     }
  2278.     else
  2279.         goto say_zero;
  2280. #endif
  2281.     case O_RMDIR:
  2282.     if (maxarg < 1)
  2283.         tmps = str_get(stab_val(defstab));
  2284.     else
  2285.         tmps = str_get(st[1]);
  2286. #ifdef TAINT
  2287.     taintproper("Insecure dependency in rmdir");
  2288. #endif
  2289. #ifdef HAS_RMDIR
  2290.     value = (double)(rmdir(tmps) >= 0);
  2291.     goto donumset;
  2292. #else
  2293.     (void)strcpy(buf,"rmdir ");
  2294.     goto one_liner;        /* see above in HAS_MKDIR */
  2295. #endif
  2296.     case O_GETPPID:
  2297. #ifdef HAS_GETPPID
  2298.     value = (double)getppid();
  2299.     goto donumset;
  2300. #else
  2301.     fatal("Unsupported function getppid");
  2302.     break;
  2303. #endif
  2304.     case O_GETPGRP:
  2305. #ifdef HAS_GETPGRP
  2306.     if (maxarg < 1)
  2307.         anum = 0;
  2308.     else
  2309.         anum = (int)str_gnum(st[1]);
  2310. #ifdef _POSIX_SOURCE
  2311.     if (anum != 0)
  2312.         fatal("POSIX getpgrp can't take an argument");
  2313.     value = (double)getpgrp();
  2314. #else
  2315.     value = (double)getpgrp(anum);
  2316. #endif
  2317.     goto donumset;
  2318. #else
  2319.     fatal("The getpgrp() function is unimplemented on this machine");
  2320.     break;
  2321. #endif
  2322.     case O_SETPGRP:
  2323. #ifdef HAS_SETPGRP
  2324.     argtype = (int)str_gnum(st[1]);
  2325.     anum = (int)str_gnum(st[2]);
  2326. #ifdef TAINT
  2327.     taintproper("Insecure dependency in setpgrp");
  2328. #endif
  2329.     value = (double)(setpgrp(argtype,anum) >= 0);
  2330.     goto donumset;
  2331. #else
  2332.     fatal("The setpgrp() function is unimplemented on this machine");
  2333.     break;
  2334. #endif
  2335.     case O_GETPRIORITY:
  2336. #ifdef HAS_GETPRIORITY
  2337.     argtype = (int)str_gnum(st[1]);
  2338.     anum = (int)str_gnum(st[2]);
  2339.     value = (double)getpriority(argtype,anum);
  2340.     goto donumset;
  2341. #else
  2342.     fatal("The getpriority() function is unimplemented on this machine");
  2343.     break;
  2344. #endif
  2345.     case O_SETPRIORITY:
  2346. #ifdef HAS_SETPRIORITY
  2347.     argtype = (int)str_gnum(st[1]);
  2348.     anum = (int)str_gnum(st[2]);
  2349.     optype = (int)str_gnum(st[3]);
  2350. #ifdef TAINT
  2351.     taintproper("Insecure dependency in setpriority");
  2352. #endif
  2353.     value = (double)(setpriority(argtype,anum,optype) >= 0);
  2354.     goto donumset;
  2355. #else
  2356.     fatal("The setpriority() function is unimplemented on this machine");
  2357.     break;
  2358. #endif
  2359.     case O_CHROOT:
  2360. #ifdef HAS_CHROOT
  2361.     if (maxarg < 1)
  2362.         tmps = str_get(stab_val(defstab));
  2363.     else
  2364.         tmps = str_get(st[1]);
  2365. #ifdef TAINT
  2366.     taintproper("Insecure dependency in chroot");
  2367. #endif
  2368.     value = (double)(chroot(tmps) >= 0);
  2369.     goto donumset;
  2370. #else
  2371.     fatal("Unsupported function chroot");
  2372.     break;
  2373. #endif
  2374.     case O_FCNTL:
  2375.     case O_IOCTL:
  2376.     if (maxarg <= 0)
  2377.         stab = last_in_stab;
  2378.     else if ((arg[1].arg_type & A_MASK) == A_WORD)
  2379.         stab = arg[1].arg_ptr.arg_stab;
  2380.     else
  2381.         stab = stabent(str_get(st[1]),TRUE);
  2382.     argtype = U_I(str_gnum(st[2]));
  2383. #ifdef TAINT
  2384.     taintproper("Insecure dependency in ioctl");
  2385. #endif
  2386.     anum = do_ctl(optype,stab,argtype,st[3]);
  2387.     if (anum == -1)
  2388.         goto say_undef;
  2389.     if (anum != 0) {
  2390.         value = (double)anum;
  2391.         goto donumset;
  2392.     }
  2393.     str_set(str,"0 but true");
  2394.     STABSET(str);
  2395.     break;
  2396.     case O_FLOCK:
  2397. #ifdef HAS_FLOCK
  2398.     if (maxarg <= 0)
  2399.         stab = last_in_stab;
  2400.     else if ((arg[1].arg_type & A_MASK) == A_WORD)
  2401.         stab = arg[1].arg_ptr.arg_stab;
  2402.     else
  2403.         stab = stabent(str_get(st[1]),TRUE);
  2404.     if (stab && stab_io(stab))
  2405.         fp = stab_io(stab)->ifp;
  2406.     else
  2407.         fp = Nullfp;
  2408.     if (fp) {
  2409.         argtype = (int)str_gnum(st[2]);
  2410.         value = (double)(flock(fileno(fp),argtype) >= 0);
  2411.     }
  2412.     else
  2413.         value = 0;
  2414.     goto donumset;
  2415. #else
  2416.     fatal("The flock() function is unimplemented on this machine");
  2417.     break;
  2418. #endif
  2419.     case O_UNSHIFT:
  2420.     ary = stab_array(arg[1].arg_ptr.arg_stab);
  2421.     if (arglast[2] - arglast[1] != 1)
  2422.         do_unshift(ary,arglast);
  2423.     else {
  2424.         STR *tmpstr = Str_new(52,0);    /* must copy the STR */
  2425.         str_sset(tmpstr,st[2]);
  2426.         aunshift(ary,1);
  2427.         (void)astore(ary,0,tmpstr);
  2428.     }
  2429.     value = (double)(ary->ary_fill + 1);
  2430.     goto donumset;
  2431.  
  2432.     case O_TRY:
  2433.     sp = do_try(arg[1].arg_ptr.arg_cmd,
  2434.         gimme,arglast);
  2435.     goto array_return;
  2436.  
  2437.     case O_EVALONCE:
  2438.     sp = do_eval(st[1], O_EVAL, curcmd->c_stash, TRUE,
  2439.         gimme,arglast);
  2440.     if (eval_root) {
  2441.         str_free(arg[1].arg_ptr.arg_str);
  2442.         arg[1].arg_ptr.arg_cmd = eval_root;
  2443.         arg[1].arg_type = (A_CMD|A_DONT);
  2444.         arg[0].arg_type = O_TRY;
  2445.     }
  2446.     goto array_return;
  2447.  
  2448.     case O_REQUIRE:
  2449.     case O_DOFILE:
  2450.     case O_EVAL:
  2451.     if (maxarg < 1)
  2452.         tmpstr = stab_val(defstab);
  2453.     else
  2454.         tmpstr =
  2455.           (arg[1].arg_type & A_MASK) != A_NULL ? st[1] : stab_val(defstab);
  2456. #ifdef TAINT
  2457.     tainted |= tmpstr->str_tainted;
  2458.     taintproper("Insecure dependency in eval");
  2459. #endif
  2460.     sp = do_eval(tmpstr, optype, curcmd->c_stash, FALSE,
  2461.         gimme,arglast);
  2462.     goto array_return;
  2463.  
  2464.     case O_FTRREAD:
  2465.     argtype = 0;
  2466.     anum = S_IRUSR;
  2467.     goto check_perm;
  2468.     case O_FTRWRITE:
  2469.     argtype = 0;
  2470.     anum = S_IWUSR;
  2471.     goto check_perm;
  2472.     case O_FTREXEC:
  2473.     argtype = 0;
  2474.     anum = S_IXUSR;
  2475.     goto check_perm;
  2476.     case O_FTEREAD:
  2477.     argtype = 1;
  2478.     anum = S_IRUSR;
  2479.     goto check_perm;
  2480.     case O_FTEWRITE:
  2481.     argtype = 1;
  2482.     anum = S_IWUSR;
  2483.     goto check_perm;
  2484.     case O_FTEEXEC:
  2485.     argtype = 1;
  2486.     anum = S_IXUSR;
  2487.       check_perm:
  2488.     if (mystat(arg,st[1]) < 0)
  2489.         goto say_undef;
  2490.     if (cando(anum,argtype,&statcache))
  2491.         goto say_yes;
  2492.     goto say_no;
  2493.  
  2494.     case O_FTIS:
  2495.     if (mystat(arg,st[1]) < 0)
  2496.         goto say_undef;
  2497.     goto say_yes;
  2498.     case O_FTEOWNED:
  2499.     case O_FTROWNED:
  2500.     if (mystat(arg,st[1]) < 0)
  2501.         goto say_undef;
  2502.     if (statcache.st_uid == (optype == O_FTEOWNED ? euid : uid) )
  2503.         goto say_yes;
  2504.     goto say_no;
  2505.     case O_FTZERO:
  2506.     if (mystat(arg,st[1]) < 0)
  2507.         goto say_undef;
  2508.     if (!statcache.st_size)
  2509.         goto say_yes;
  2510.     goto say_no;
  2511.     case O_FTSIZE:
  2512.     if (mystat(arg,st[1]) < 0)
  2513.         goto say_undef;
  2514.     value = (double)statcache.st_size;
  2515.     goto donumset;
  2516.  
  2517.     case O_FTMTIME:
  2518.     if (mystat(arg,st[1]) < 0)
  2519.         goto say_undef;
  2520.     value = (double)(basetime - statcache.st_mtime) / 86400.0;
  2521.     goto donumset;
  2522.     case O_FTATIME:
  2523.     if (mystat(arg,st[1]) < 0)
  2524.         goto say_undef;
  2525.     value = (double)(basetime - statcache.st_atime) / 86400.0;
  2526.     goto donumset;
  2527.     case O_FTCTIME:
  2528.     if (mystat(arg,st[1]) < 0)
  2529.         goto say_undef;
  2530.     value = (double)(basetime - statcache.st_ctime) / 86400.0;
  2531.     goto donumset;
  2532.  
  2533.     case O_FTSOCK:
  2534.     if (mystat(arg,st[1]) < 0)
  2535.         goto say_undef;
  2536.     if (S_ISSOCK(statcache.st_mode))
  2537.         goto say_yes;
  2538.     goto say_no;
  2539.     case O_FTCHR:
  2540.     if (mystat(arg,st[1]) < 0)
  2541.         goto say_undef;
  2542.     if (S_ISCHR(statcache.st_mode))
  2543.         goto say_yes;
  2544.     goto say_no;
  2545.     case O_FTBLK:
  2546.     if (mystat(arg,st[1]) < 0)
  2547.         goto say_undef;
  2548.     if (S_ISBLK(statcache.st_mode))
  2549.         goto say_yes;
  2550.     goto say_no;
  2551.     case O_FTFILE:
  2552.     if (mystat(arg,st[1]) < 0)
  2553.         goto say_undef;
  2554.     if (S_ISREG(statcache.st_mode))
  2555.         goto say_yes;
  2556.     goto say_no;
  2557.     case O_FTDIR:
  2558.     if (mystat(arg,st[1]) < 0)
  2559.         goto say_undef;
  2560.     if (S_ISDIR(statcache.st_mode))
  2561.         goto say_yes;
  2562.     goto say_no;
  2563.     case O_FTPIPE:
  2564.     if (mystat(arg,st[1]) < 0)
  2565.         goto say_undef;
  2566.     if (S_ISFIFO(statcache.st_mode))
  2567.         goto say_yes;
  2568.     goto say_no;
  2569.     case O_FTLINK:
  2570.     if (mylstat(arg,st[1]) < 0)
  2571.         goto say_undef;
  2572.     if (S_ISLNK(statcache.st_mode))
  2573.         goto say_yes;
  2574.     goto say_no;
  2575.     case O_SYMLINK:
  2576. #ifdef HAS_SYMLINK
  2577.     tmps = str_get(st[1]);
  2578.     tmps2 = str_get(st[2]);
  2579. #ifdef TAINT
  2580.     taintproper("Insecure dependency in symlink");
  2581. #endif
  2582.     value = (double)(symlink(tmps,tmps2) >= 0);
  2583.     goto donumset;
  2584. #else
  2585.     fatal("Unsupported function symlink");
  2586. #endif
  2587.     case O_READLINK:
  2588. #ifdef HAS_SYMLINK
  2589.     if (maxarg < 1)
  2590.         tmps = str_get(stab_val(defstab));
  2591.     else
  2592.         tmps = str_get(st[1]);
  2593.     anum = readlink(tmps,buf,sizeof buf);
  2594.     if (anum < 0)
  2595.         goto say_undef;
  2596.     str_nset(str,buf,anum);
  2597.     break;
  2598. #else
  2599.     goto say_undef;        /* just pretend it's a normal file */
  2600. #endif
  2601.     case O_FTSUID:
  2602. #ifdef S_ISUID
  2603.     anum = S_ISUID;
  2604.     goto check_xid;
  2605. #else
  2606.     goto say_no;
  2607. #endif
  2608.     case O_FTSGID:
  2609. #ifdef S_ISGID
  2610.     anum = S_ISGID;
  2611.     goto check_xid;
  2612. #else
  2613.     goto say_no;
  2614. #endif
  2615.     case O_FTSVTX:
  2616. #ifdef S_ISVTX
  2617.     anum = S_ISVTX;
  2618. #else
  2619.     goto say_no;
  2620. #endif
  2621.       check_xid:
  2622.     if (mystat(arg,st[1]) < 0)
  2623.         goto say_undef;
  2624.     if (statcache.st_mode & anum)
  2625.         goto say_yes;
  2626.     goto say_no;
  2627.     case O_FTTTY:
  2628.     if (arg[1].arg_type & A_DONT) {
  2629.         stab = arg[1].arg_ptr.arg_stab;
  2630.         tmps = "";
  2631.     }
  2632.     else
  2633.         stab = stabent(tmps = str_get(st[1]),FALSE);
  2634.     if (stab && stab_io(stab) && stab_io(stab)->ifp)
  2635.         anum = fileno(stab_io(stab)->ifp);
  2636.     else if (isDIGIT(*tmps))
  2637.         anum = atoi(tmps);
  2638.     else
  2639.         goto say_undef;
  2640.     if (isatty(anum))
  2641.         goto say_yes;
  2642.     goto say_no;
  2643.     case O_FTTEXT:
  2644.     case O_FTBINARY:
  2645.     str = do_fttext(arg,st[1]);
  2646.     break;
  2647. #ifdef HAS_SOCKET
  2648.     case O_SOCKET:
  2649.     if ((arg[1].arg_type & A_MASK) == A_WORD)
  2650.         stab = arg[1].arg_ptr.arg_stab;
  2651.     else
  2652.         stab = stabent(str_get(st[1]),TRUE);
  2653. #ifndef lint
  2654.     value = (double)do_socket(stab,arglast);
  2655. #else
  2656.     (void)do_socket(stab,arglast);
  2657. #endif
  2658.     goto donumset;
  2659.     case O_BIND:
  2660.     if ((arg[1].arg_type & A_MASK) == A_WORD)
  2661.         stab = arg[1].arg_ptr.arg_stab;
  2662.     else
  2663.         stab = stabent(str_get(st[1]),TRUE);
  2664. #ifndef lint
  2665.     value = (double)do_bind(stab,arglast);
  2666. #else
  2667.     (void)do_bind(stab,arglast);
  2668. #endif
  2669.     goto donumset;
  2670.     case O_CONNECT:
  2671.     if ((arg[1].arg_type & A_MASK) == A_WORD)
  2672.         stab = arg[1].arg_ptr.arg_stab;
  2673.     else
  2674.         stab = stabent(str_get(st[1]),TRUE);
  2675. #ifndef lint
  2676.     value = (double)do_connect(stab,arglast);
  2677. #else
  2678.     (void)do_connect(stab,arglast);
  2679. #endif
  2680.     goto donumset;
  2681.     case O_LISTEN:
  2682.     if ((arg[1].arg_type & A_MASK) == A_WORD)
  2683.         stab = arg[1].arg_ptr.arg_stab;
  2684.     else
  2685.         stab = stabent(str_get(st[1]),TRUE);
  2686. #ifndef lint
  2687.     value = (double)do_listen(stab,arglast);
  2688. #else
  2689.     (void)do_listen(stab,arglast);
  2690. #endif
  2691.     goto donumset;
  2692.     case O_ACCEPT:
  2693.     if ((arg[1].arg_type & A_MASK) == A_WORD)
  2694.         stab = arg[1].arg_ptr.arg_stab;
  2695.     else
  2696.         stab = stabent(str_get(st[1]),TRUE);
  2697.     if ((arg[2].arg_type & A_MASK) == A_WORD)
  2698.         stab2 = arg[2].arg_ptr.arg_stab;
  2699.     else
  2700.         stab2 = stabent(str_get(st[2]),TRUE);
  2701.     do_accept(str,stab,stab2);
  2702.     STABSET(str);
  2703.     break;
  2704.     case O_GHBYNAME:
  2705.     if (maxarg < 1)
  2706.         goto say_undef;
  2707.     case O_GHBYADDR:
  2708.     case O_GHOSTENT:
  2709.     sp = do_ghent(optype,
  2710.       gimme,arglast);
  2711.     goto array_return;
  2712.     case O_GNBYNAME:
  2713.     if (maxarg < 1)
  2714.         goto say_undef;
  2715.     case O_GNBYADDR:
  2716.     case O_GNETENT:
  2717.     sp = do_gnent(optype,
  2718.       gimme,arglast);
  2719.     goto array_return;
  2720.     case O_GPBYNAME:
  2721.     if (maxarg < 1)
  2722.         goto say_undef;
  2723.     case O_GPBYNUMBER:
  2724.     case O_GPROTOENT:
  2725.     sp = do_gpent(optype,
  2726.       gimme,arglast);
  2727.     goto array_return;
  2728.     case O_GSBYNAME:
  2729.     if (maxarg < 1)
  2730.         goto say_undef;
  2731.     case O_GSBYPORT:
  2732.     case O_GSERVENT:
  2733.     sp = do_gsent(optype,
  2734.       gimme,arglast);
  2735.     goto array_return;
  2736.     case O_SHOSTENT:
  2737.     value = (double) sethostent((int)str_gnum(st[1]));
  2738.     goto donumset;
  2739.     case O_SNETENT:
  2740.     value = (double) setnetent((int)str_gnum(st[1]));
  2741.     goto donumset;
  2742.     case O_SPROTOENT:
  2743.     value = (double) setprotoent((int)str_gnum(st[1]));
  2744.     goto donumset;
  2745.     case O_SSERVENT:
  2746.     value = (double) setservent((int)str_gnum(st[1]));
  2747.     goto donumset;
  2748.     case O_EHOSTENT:
  2749.     value = (double) endhostent();
  2750.     goto donumset;
  2751.     case O_ENETENT:
  2752.     value = (double) endnetent();
  2753.     goto donumset;
  2754.     case O_EPROTOENT:
  2755.     value = (double) endprotoent();
  2756.     goto donumset;
  2757.     case O_ESERVENT:
  2758.     value = (double) endservent();
  2759.     goto donumset;
  2760.     case O_SOCKPAIR:
  2761.     if ((arg[1].arg_type & A_MASK) == A_WORD)
  2762.         stab = arg[1].arg_ptr.arg_stab;
  2763.     else
  2764.         stab = stabent(str_get(st[1]),TRUE);
  2765.     if ((arg[2].arg_type & A_MASK) == A_WORD)
  2766.         stab2 = arg[2].arg_ptr.arg_stab;
  2767.     else
  2768.         stab2 = stabent(str_get(st[2]),TRUE);
  2769. #ifndef lint
  2770.     value = (double)do_spair(stab,stab2,arglast);
  2771. #else
  2772.     (void)do_spair(stab,stab2,arglast);
  2773. #endif
  2774.     goto donumset;
  2775.     case O_SHUTDOWN:
  2776.     if ((arg[1].arg_type & A_MASK) == A_WORD)
  2777.         stab = arg[1].arg_ptr.arg_stab;
  2778.     else
  2779.         stab = stabent(str_get(st[1]),TRUE);
  2780.     value = (double)do_shutdown(stab,arglast);
  2781.     goto donumset;
  2782.     case O_GSOCKOPT:
  2783.     case O_SSOCKOPT:
  2784.     if ((arg[1].arg_type & A_MASK) == A_WORD)
  2785.         stab = arg[1].arg_ptr.arg_stab;
  2786.     else
  2787.         stab = stabent(str_get(st[1]),TRUE);
  2788.     sp = do_sopt(optype,stab,arglast);
  2789.     goto array_return;
  2790.     case O_GETSOCKNAME:
  2791.     case O_GETPEERNAME:
  2792.     if ((arg[1].arg_type & A_MASK) == A_WORD)
  2793.         stab = arg[1].arg_ptr.arg_stab;
  2794.     else
  2795.         stab = stabent(str_get(st[1]),TRUE);
  2796.     if (!stab)
  2797.         goto say_undef;
  2798.     sp = do_getsockname(optype,stab,arglast);
  2799.     goto array_return;
  2800.  
  2801. #else /* HAS_SOCKET not defined */
  2802.     case O_SOCKET:
  2803.     case O_BIND:
  2804.     case O_CONNECT:
  2805.     case O_LISTEN:
  2806.     case O_ACCEPT:
  2807.     case O_SOCKPAIR:
  2808.     case O_GHBYNAME:
  2809.     case O_GHBYADDR:
  2810.     case O_GHOSTENT:
  2811.     case O_GNBYNAME:
  2812.     case O_GNBYADDR:
  2813.     case O_GNETENT:
  2814.     case O_GPBYNAME:
  2815.     case O_GPBYNUMBER:
  2816.     case O_GPROTOENT:
  2817.     case O_GSBYNAME:
  2818.     case O_GSBYPORT:
  2819.     case O_GSERVENT:
  2820.     case O_SHOSTENT:
  2821.     case O_SNETENT:
  2822.     case O_SPROTOENT:
  2823.     case O_SSERVENT:
  2824.     case O_EHOSTENT:
  2825.     case O_ENETENT:
  2826.     case O_EPROTOENT:
  2827.     case O_ESERVENT:
  2828.     case O_SHUTDOWN:
  2829.     case O_GSOCKOPT:
  2830.     case O_SSOCKOPT:
  2831.     case O_GETSOCKNAME:
  2832.     case O_GETPEERNAME:
  2833.       badsock:
  2834.     fatal("Unsupported socket function");
  2835. #endif /* HAS_SOCKET */
  2836.     case O_SSELECT:
  2837. #ifdef HAS_SELECT
  2838.     sp = do_select(gimme,arglast);
  2839.     goto array_return;
  2840. #else
  2841.     fatal("select not implemented");
  2842. #endif
  2843.     case O_FILENO:
  2844.     if (maxarg < 1)
  2845.         goto say_undef;
  2846.     if ((arg[1].arg_type & A_MASK) == A_WORD)
  2847.         stab = arg[1].arg_ptr.arg_stab;
  2848.     else
  2849.         stab = stabent(str_get(st[1]),TRUE);
  2850.     if (!stab || !(stio = stab_io(stab)) || !(fp = stio->ifp))
  2851.         goto say_undef;
  2852.     value = fileno(fp);
  2853.     goto donumset;
  2854.     case O_BINMODE:
  2855.     if (maxarg < 1)
  2856.         goto say_undef;
  2857.     if ((arg[1].arg_type & A_MASK) == A_WORD)
  2858.         stab = arg[1].arg_ptr.arg_stab;
  2859.     else
  2860.         stab = stabent(str_get(st[1]),TRUE);
  2861.     if (!stab || !(stio = stab_io(stab)) || !(fp = stio->ifp))
  2862.         goto say_undef;
  2863. #ifdef MSDOS
  2864.     str_set(str, (setmode(fileno(fp), O_BINARY) != -1) ? Yes : No);
  2865. #else
  2866.     str_set(str, Yes);
  2867. #endif
  2868.     STABSET(str);
  2869.     break;
  2870.     case O_VEC:
  2871.     sp = do_vec(str == st[1], arg->arg_ptr.arg_str, arglast);
  2872.     goto array_return;
  2873.     case O_GPWNAM:
  2874.     case O_GPWUID:
  2875.     case O_GPWENT:
  2876. #ifdef HAS_PASSWD
  2877.     sp = do_gpwent(optype,
  2878.       gimme,arglast);
  2879.     goto array_return;
  2880.     case O_SPWENT:
  2881.     value = (double) setpwent();
  2882.     goto donumset;
  2883.     case O_EPWENT:
  2884.     value = (double) endpwent();
  2885.     goto donumset;
  2886. #else
  2887.     case O_EPWENT:
  2888.     case O_SPWENT:
  2889.     fatal("Unsupported password function");
  2890.     break;
  2891. #endif
  2892.     case O_GGRNAM:
  2893.     case O_GGRGID:
  2894.     case O_GGRENT:
  2895. #ifdef HAS_GROUP
  2896.     sp = do_ggrent(optype,
  2897.       gimme,arglast);
  2898.     goto array_return;
  2899.     case O_SGRENT:
  2900.     value = (double) setgrent();
  2901.     goto donumset;
  2902.     case O_EGRENT:
  2903.     value = (double) endgrent();
  2904.     goto donumset;
  2905. #else
  2906.     case O_EGRENT:
  2907.     case O_SGRENT:
  2908.     fatal("Unsupported group function");
  2909.     break;
  2910. #endif
  2911.     case O_GETLOGIN:
  2912. #ifdef HAS_GETLOGIN
  2913.     if (!(tmps = getlogin()))
  2914.         goto say_undef;
  2915.     str_set(str,tmps);
  2916. #else
  2917.     fatal("Unsupported function getlogin");
  2918. #endif
  2919.     break;
  2920.     case O_OPEN_DIR:
  2921.     case O_READDIR:
  2922.     case O_TELLDIR:
  2923.     case O_SEEKDIR:
  2924.     case O_REWINDDIR:
  2925.     case O_CLOSEDIR:
  2926.     if (maxarg < 1)
  2927.         goto say_undef;
  2928.     if ((arg[1].arg_type & A_MASK) == A_WORD)
  2929.         stab = arg[1].arg_ptr.arg_stab;
  2930.     else
  2931.         stab = stabent(str_get(st[1]),TRUE);
  2932.     if (!stab)
  2933.         goto say_undef;
  2934.     sp = do_dirop(optype,stab,gimme,arglast);
  2935.     goto array_return;
  2936.     case O_SYSCALL:
  2937.     value = (double)do_syscall(arglast);
  2938.     goto donumset;
  2939.     case O_PIPE:
  2940. #ifdef HAS_PIPE
  2941.     if ((arg[1].arg_type & A_MASK) == A_WORD)
  2942.         stab = arg[1].arg_ptr.arg_stab;
  2943.     else
  2944.         stab = stabent(str_get(st[1]),TRUE);
  2945.     if ((arg[2].arg_type & A_MASK) == A_WORD)
  2946.         stab2 = arg[2].arg_ptr.arg_stab;
  2947.     else
  2948.         stab2 = stabent(str_get(st[2]),TRUE);
  2949.     do_pipe(str,stab,stab2);
  2950.     STABSET(str);
  2951. #else
  2952.     fatal("Unsupported function pipe");
  2953. #endif
  2954.     break;
  2955.     }
  2956.  
  2957.   normal_return:
  2958.     st[1] = str;
  2959. #ifdef DEBUGGING
  2960.     if (debug) {
  2961.     dlevel--;
  2962.     if (debug & 8)
  2963.         deb("%s RETURNS \"%s\"\n",opname[optype],str_get(str));
  2964.     }
  2965. #endif
  2966.     return arglast[0] + 1;
  2967. }
  2968.  
  2969. #else
  2970.  
  2971. #include <Math.h>
  2972.  
  2973. #define SMALLSWITCHES
  2974.  
  2975. typedef enum {
  2976.     R_nojump,
  2977.     R_array_return,
  2978.     R_say_no,
  2979.     R_re_eval,
  2980.     R_badsock,
  2981.     R_say_yes,
  2982.     R_say_undef,
  2983.     R_donumset,
  2984.     R_say_zero} EvalResult;
  2985.  
  2986. typedef struct {
  2987.     ARG *        arg;
  2988.     int         gimme;
  2989.     int         sp;
  2990.     STR *        str;
  2991.     int         anum;
  2992.     int         optype;
  2993.     STR **        st;
  2994.     int         maxarg;
  2995.     double         value;
  2996.     char *        tmps;
  2997.     char *        tmps2;
  2998.     int         argflags;
  2999.     int         argtype;
  3000.     union argptr     argptr;
  3001.     int         arglast[8];    /* highest ed->sp for arg--valid only for non-O_LIST args */
  3002.     unsigned long     tmplong;
  3003.     long        longo;
  3004.     time_t         when;
  3005.     FILE *        fp;
  3006.     STR *        tmpstr;
  3007.     FCMD *        form;
  3008.     STAB *        stab;
  3009.     ARRAY *        ary;
  3010.     bool         assigning;
  3011. } EvalData;
  3012.  
  3013. char *crypt(), *getenv();
  3014. extern void grow_dlevel();
  3015.  
  3016. EvalResult eval1(EvalData * ed)
  3017. {
  3018.     switch (ed->optype) {
  3019.     case O_RCAT:
  3020.     STABSET(ed->str);
  3021.     break;
  3022.     case O_ITEM:
  3023.     if (ed->gimme == G_ARRAY)
  3024.         goto array_return;
  3025.     /* FALL THROUGH */
  3026.     case O_SCALAR:
  3027.     STR_SSET(ed->str,ed->st[1]);
  3028.     STABSET(ed->str);
  3029.     break;
  3030.     case O_ITEM2:
  3031.     if (ed->gimme == G_ARRAY)
  3032.         goto array_return;
  3033.     --ed->anum;
  3034.     STR_SSET(ed->str,ed->st[ed->arglast[ed->anum]-ed->arglast[0]]);
  3035.     STABSET(ed->str);
  3036.     break;
  3037.     case O_ITEM3:
  3038.     if (ed->gimme == G_ARRAY)
  3039.     goto array_return;
  3040.     --ed->anum;
  3041.     STR_SSET(ed->str,ed->st[ed->arglast[ed->anum]-ed->arglast[0]]);
  3042.     STABSET(ed->str);
  3043.     break;
  3044.     case O_CONCAT:
  3045.     STR_SSET(ed->str,ed->st[1]);
  3046.     str_scat(ed->str,ed->st[2]);
  3047.     STABSET(ed->str);
  3048.     break;
  3049.     case O_REPEAT:
  3050.     if (ed->gimme == G_ARRAY && ed->arg[1].arg_flags & AF_ARYOK) {
  3051.         ed->sp = do_repeatary(ed->arglast);
  3052.         goto array_return;
  3053.     }
  3054.     STR_SSET(ed->str,ed->st[ed->arglast[1] - ed->arglast[0]]);
  3055.     ed->anum = (int)str_gnum(ed->st[ed->arglast[2] - ed->arglast[0]]);
  3056.     if (ed->anum >= 1) {
  3057.         ed->tmpstr = Str_new(50, 0);
  3058.         ed->tmps = str_get(ed->str);
  3059.         str_nset(ed->tmpstr,ed->tmps,ed->str->str_cur);
  3060.         ed->tmps = str_get(ed->tmpstr);    /* force to be string */
  3061.         STR_GROW(ed->str, (ed->anum * ed->str->str_cur) + 1);
  3062.         repeatcpy(ed->str->str_ptr, ed->tmps, ed->tmpstr->str_cur, ed->anum);
  3063.         ed->str->str_cur *= ed->anum;
  3064.         ed->str->str_ptr[ed->str->str_cur] = '\0';
  3065.         ed->str->str_nok = 0;
  3066.         str_free(ed->tmpstr);
  3067.     }
  3068.     else
  3069.         str_sset(ed->str,&str_no);
  3070.     STABSET(ed->str);
  3071.     break;
  3072.     case O_MATCH:
  3073.     ed->sp = do_match(ed->str,ed->arg,
  3074.       ed->gimme,ed->arglast);
  3075.     if (ed->gimme == G_ARRAY)
  3076.         goto array_return;
  3077.     STABSET(ed->str);
  3078.     break;
  3079.     case O_NMATCH:
  3080.     ed->sp = do_match(ed->str,ed->arg,
  3081.       G_SCALAR,ed->arglast);
  3082.     str_sset(ed->str, str_true(ed->str) ? &str_no : &str_yes);
  3083.     STABSET(ed->str);
  3084.     break;
  3085.     case O_SUBST:
  3086.     ed->sp = do_subst(ed->str,ed->arg,ed->arglast[0]);
  3087.     goto array_return;
  3088.     case O_NSUBST:
  3089.     ed->sp = do_subst(ed->str,ed->arg,ed->arglast[0]);
  3090.     ed->str = ed->arg->arg_ptr.arg_str;
  3091.     str_set(ed->str, str_true(ed->str) ? No : Yes);
  3092.     goto array_return;
  3093.     case O_ASSIGN:
  3094.     if (ed->arg[1].arg_flags & AF_ARYOK) {
  3095.         if (ed->arg->arg_len == 1) {
  3096.         ed->arg->arg_type = O_LOCAL;
  3097.         goto local;
  3098.         }
  3099.         else {
  3100.         ed->arg->arg_type = O_AASSIGN;
  3101.         goto aassign;
  3102.         }
  3103.     }
  3104.     else {
  3105.         ed->arg->arg_type = O_SASSIGN;
  3106.         goto sassign;
  3107.     }
  3108.     case O_LOCAL:
  3109.       local:
  3110.     ed->arglast[2] = ed->arglast[1];    /* push a null array */
  3111.     /* FALL THROUGH */
  3112.     case O_AASSIGN:
  3113.       aassign:
  3114.     ed->sp = do_assign(ed->arg,
  3115.       ed->gimme,ed->arglast);
  3116.     goto array_return;
  3117.     case O_SASSIGN:
  3118.       sassign:
  3119.     STR_SSET(ed->str, ed->st[2]);
  3120.     STABSET(ed->str);
  3121.     break;
  3122.     case O_CHOP:
  3123.     ed->st -= ed->arglast[0];
  3124.     ed->str = ed->arg->arg_ptr.arg_str;
  3125.     for (ed->sp = ed->arglast[0] + 1; ed->sp <= ed->arglast[1]; ed->sp++)
  3126.         do_chop(ed->str,ed->st[ed->sp]);
  3127.     ed->st += ed->arglast[0];
  3128.     break;
  3129.     case O_DEFINED:
  3130.     if (ed->arg[1].arg_type & A_DONT) {
  3131.         ed->sp = do_defined(ed->str,ed->arg,
  3132.           ed->gimme,ed->arglast);
  3133.         goto array_return;
  3134.     }
  3135.     else if (ed->str->str_pok || ed->str->str_nok)
  3136.         goto say_yes;
  3137.     goto say_no;
  3138.     case O_UNDEF:
  3139.     if (ed->arg[1].arg_type & A_DONT) {
  3140.         ed->sp = do_undef(ed->str,ed->arg,
  3141.           ed->gimme,ed->arglast);
  3142.         goto array_return;
  3143.     }
  3144.     else if (ed->str != stab_val(defstab)) {
  3145.         if (ed->str->str_len) {
  3146.         if (ed->str->str_state == SS_INCR)
  3147.             Str_Grow(ed->str,0);
  3148.         Safefree(ed->str->str_ptr);
  3149.         ed->str->str_ptr = Nullch;
  3150.         ed->str->str_len = 0;
  3151.         }
  3152.         ed->str->str_pok = ed->str->str_nok = 0;
  3153.         STABSET(ed->str);
  3154.     }
  3155.     goto say_undef;
  3156.     case O_STUDY:
  3157.     ed->sp = do_study(ed->str,ed->arg,
  3158.       ed->gimme,ed->arglast);
  3159.     goto array_return;
  3160.     case O_POW:
  3161.     ed->value = str_gnum(ed->st[1]);
  3162.     ed->value = pow(ed->value,str_gnum(ed->st[2]));
  3163.     goto donumset;
  3164.     case O_MULTIPLY:
  3165.     ed->value = str_gnum(ed->st[1]);
  3166.     ed->value *= str_gnum(ed->st[2]);
  3167.     goto donumset;
  3168.     case O_DIVIDE:
  3169.     if ((ed->value = str_gnum(ed->st[2])) == 0.0)
  3170.         fatal("Illegal division by zero");
  3171.     ed->value = str_gnum(ed->st[1]) / ed->value;
  3172.     goto donumset;
  3173.     case O_MODULO:
  3174.     ed->tmplong = (long) str_gnum(ed->st[2]);
  3175.         if (ed->tmplong == 0L)
  3176.             fatal("Illegal modulus zero");
  3177.     ed->longo = (long)str_gnum(ed->st[1]);
  3178.     if (ed->longo >= 0)
  3179.         ed->value = (double)(ed->longo % ed->tmplong);
  3180.     else
  3181.         ed->value = (double)(ed->tmplong - ((-ed->longo - 1) % ed->tmplong)) - 1;
  3182.     goto donumset;
  3183.     case O_ADD:
  3184.     ed->value = str_gnum(ed->st[1]);
  3185.     ed->value += str_gnum(ed->st[2]);
  3186.     goto donumset;
  3187.     case O_SUBTRACT:
  3188.     ed->value = str_gnum(ed->st[1]);
  3189.     ed->value -= str_gnum(ed->st[2]);
  3190.     goto donumset;
  3191.     case O_LEFT_SHIFT:
  3192.     ed->value = str_gnum(ed->st[1]);
  3193.     ed->anum = (int)str_gnum(ed->st[2]);
  3194.     ed->value = (double)(U_L(ed->value) << ed->anum);
  3195.     goto donumset;
  3196.     case O_RIGHT_SHIFT:
  3197.     ed->value = str_gnum(ed->st[1]);
  3198.     ed->anum = (int)str_gnum(ed->st[2]);
  3199.     ed->value = (double)(U_L(ed->value) >> ed->anum);
  3200.     goto donumset;
  3201.     case O_LT:
  3202.     ed->value = str_gnum(ed->st[1]);
  3203.     ed->value = (ed->value < str_gnum(ed->st[2])) ? 1.0 : 0.0;
  3204.     goto donumset;
  3205.     case O_GT:
  3206.     ed->value = str_gnum(ed->st[1]);
  3207.     ed->value = (ed->value > str_gnum(ed->st[2])) ? 1.0 : 0.0;
  3208.     goto donumset;
  3209.     case O_LE:
  3210.     ed->value = str_gnum(ed->st[1]);
  3211.     ed->value = (ed->value <= str_gnum(ed->st[2])) ? 1.0 : 0.0;
  3212.     goto donumset;
  3213.     case O_GE:
  3214.     ed->value = str_gnum(ed->st[1]);
  3215.     ed->value = (ed->value >= str_gnum(ed->st[2])) ? 1.0 : 0.0;
  3216.     goto donumset;
  3217.     case O_EQ:
  3218.     if (dowarn) {
  3219.         if ((!ed->st[1]->str_nok && !looks_like_number(ed->st[1])) ||
  3220.         (!ed->st[2]->str_nok && !looks_like_number(ed->st[2])) )
  3221.         warn("Possible use of == on string ed->value");
  3222.     }
  3223.     ed->value = str_gnum(ed->st[1]);
  3224.     ed->value = (ed->value == str_gnum(ed->st[2])) ? 1.0 : 0.0;
  3225.     goto donumset;
  3226.     case O_NE:
  3227.     ed->value = str_gnum(ed->st[1]);
  3228.     ed->value = (ed->value != str_gnum(ed->st[2])) ? 1.0 : 0.0;
  3229.     goto donumset;
  3230.     case O_NCMP:
  3231.     ed->value = str_gnum(ed->st[1]);
  3232.     ed->value -= str_gnum(ed->st[2]);
  3233.     if (ed->value > 0.0)
  3234.         ed->value = 1.0;
  3235.     else if (ed->value < 0.0)
  3236.         ed->value = -1.0;
  3237.     goto donumset;
  3238.     case O_BIT_AND:
  3239.     if (!sawvec || ed->st[1]->str_nok || ed->st[2]->str_nok) {
  3240.         ed->value = str_gnum(ed->st[1]);
  3241.         ed->value = (double)(U_L(ed->value) & U_L(str_gnum(ed->st[2])));
  3242.         goto donumset;
  3243.     }
  3244.     else
  3245.         do_vop(ed->optype,ed->str,ed->st[1],ed->st[2]);
  3246.     break;
  3247.     case O_XOR:
  3248.     if (!sawvec || ed->st[1]->str_nok || ed->st[2]->str_nok) {
  3249.         ed->value = str_gnum(ed->st[1]);
  3250.         ed->value = (double)(U_L(ed->value) ^ U_L(str_gnum(ed->st[2])));
  3251.         goto donumset;
  3252.     }
  3253.     else
  3254.         do_vop(ed->optype,ed->str,ed->st[1],ed->st[2]);
  3255.     break;
  3256.     case O_BIT_OR:
  3257.     if (!sawvec || ed->st[1]->str_nok || ed->st[2]->str_nok) {
  3258.         ed->value = str_gnum(ed->st[1]);
  3259.         ed->value = (double)(U_L(ed->value) | U_L(str_gnum(ed->st[2])));
  3260.         goto donumset;
  3261.     }
  3262.     else
  3263.         do_vop(ed->optype,ed->str,ed->st[1],ed->st[2]);
  3264.     break;
  3265. /* use register in evaluating str_true() */
  3266.     case O_AND:
  3267.     if (str_true(ed->st[1])) {
  3268.         ed->anum = 2;
  3269.         ed->optype = O_ITEM2;
  3270.         ed->argflags = ed->arg[ed->anum].arg_flags;
  3271.         if (ed->gimme == G_ARRAY)
  3272.         ed->argflags |= AF_ARYOK;
  3273.         ed->argtype = ed->arg[ed->anum].arg_type & A_MASK;
  3274.         ed->argptr = ed->arg[ed->anum].arg_ptr;
  3275.         ed->maxarg = ed->anum = 1;
  3276.         ed->sp = ed->arglast[0];
  3277.         ed->st -= ed->sp;
  3278.         goto re_eval;
  3279.     }
  3280.     else {
  3281.         if (ed->assigning) {
  3282.         str_sset(ed->str, ed->st[1]);
  3283.         STABSET(ed->str);
  3284.         }
  3285.         else
  3286.         ed->str = ed->st[1];
  3287.         break;
  3288.     }
  3289.     case O_OR:
  3290.     if (str_true(ed->st[1])) {
  3291.         if (ed->assigning) {
  3292.         str_sset(ed->str, ed->st[1]);
  3293.         STABSET(ed->str);
  3294.         }
  3295.         else
  3296.         ed->str = ed->st[1];
  3297.         break;
  3298.     }
  3299.     else {
  3300.         ed->anum = 2;
  3301.         ed->optype = O_ITEM2;
  3302.         ed->argflags = ed->arg[ed->anum].arg_flags;
  3303.         if (ed->gimme == G_ARRAY)
  3304.         ed->argflags |= AF_ARYOK;
  3305.         ed->argtype = ed->arg[ed->anum].arg_type & A_MASK;
  3306.         ed->argptr = ed->arg[ed->anum].arg_ptr;
  3307.         ed->maxarg = ed->anum = 1;
  3308.         ed->sp = ed->arglast[0];
  3309.         ed->st -= ed->sp;
  3310.         goto re_eval;
  3311.     }
  3312.     case O_COND_EXPR:
  3313.     ed->anum = (str_true(ed->st[1]) ? 2 : 3);
  3314.     ed->optype = (ed->anum == 2 ? O_ITEM2 : O_ITEM3);
  3315.     ed->argflags = ed->arg[ed->anum].arg_flags;
  3316.     if (ed->gimme == G_ARRAY)
  3317.         ed->argflags |= AF_ARYOK;
  3318.     ed->argtype = ed->arg[ed->anum].arg_type & A_MASK;
  3319.     ed->argptr = ed->arg[ed->anum].arg_ptr;
  3320.     ed->maxarg = ed->anum = 1;
  3321.     ed->sp = ed->arglast[0];
  3322.     ed->st -= ed->sp;
  3323.     goto re_eval;
  3324.     case O_COMMA:
  3325.     if (ed->gimme == G_ARRAY)
  3326.         goto array_return;
  3327.     ed->str = ed->st[2];
  3328.     break;
  3329.     case O_NEGATE:
  3330.     ed->value = -str_gnum(ed->st[1]);
  3331.     goto donumset;
  3332.     case O_NOT:
  3333. #ifdef NOTNOT
  3334.     { char xxx = str_true(st[1]); ed->value = (double) !xxx; }
  3335. #else
  3336.       ed->value = (double) !str_true(ed->st[1]);
  3337. #endif
  3338.     goto donumset;
  3339.     case O_COMPLEMENT:
  3340.     if (!sawvec || ed->st[1]->str_nok) {
  3341.         ed->value = (double) ~U_L(str_gnum(ed->st[1]));
  3342.         goto donumset;
  3343.     }
  3344.     else {
  3345.         STR_SSET(ed->str,ed->st[1]);
  3346.         ed->tmps = str_get(ed->str);
  3347.         for (ed->anum = ed->str->str_cur; ed->anum; ed->anum--, ed->tmps++)
  3348.         *ed->tmps = ~*ed->tmps;
  3349.     }
  3350.     break;
  3351.     case O_SELECT:
  3352.     stab_fullname(ed->str,defoutstab);
  3353.     if (ed->maxarg > 0) {
  3354.         if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  3355.         defoutstab = ed->arg[1].arg_ptr.arg_stab;
  3356.         else
  3357.         defoutstab = stabent(str_get(ed->st[1]),TRUE);
  3358.         if (!stab_io(defoutstab))
  3359.         stab_io(defoutstab) = stio_new();
  3360.         curoutstab = defoutstab;
  3361.     }
  3362.     STABSET(ed->str);
  3363.     break;
  3364.     case O_WRITE:
  3365.     if (ed->maxarg == 0)
  3366.         ed->stab = defoutstab;
  3367.     else if ((ed->arg[1].arg_type & A_MASK) == A_WORD) {
  3368.         if (!(ed->stab = ed->arg[1].arg_ptr.arg_stab))
  3369.         ed->stab = defoutstab;
  3370.     }
  3371.     else
  3372.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  3373.     if (!stab_io(ed->stab)) {
  3374.         str_set(ed->str, No);
  3375.         STABSET(ed->str);
  3376.         break;
  3377.     }
  3378.     curoutstab = ed->stab;
  3379.     ed->fp = stab_io(ed->stab)->ofp;
  3380.     debarg = ed->arg;
  3381.     if (stab_io(ed->stab)->fmt_stab)
  3382.         ed->form = stab_form(stab_io(ed->stab)->fmt_stab);
  3383.     else
  3384.         ed->form = stab_form(ed->stab);
  3385.     if (!ed->form || !ed->fp) {
  3386.         if (dowarn) {
  3387.         if (ed->form)
  3388.             warn("No format for filehandle");
  3389.         else {
  3390.             if (stab_io(ed->stab)->ifp)
  3391.             warn("Filehandle only opened for input");
  3392.             else
  3393.             warn("Write on closed filehandle");
  3394.         }
  3395.         }
  3396.         str_set(ed->str, No);
  3397.         STABSET(ed->str);
  3398.         break;
  3399.     }
  3400.     format(&outrec,ed->form,ed->sp);
  3401.     do_write(&outrec,ed->stab,ed->sp);
  3402.     if (stab_io(ed->stab)->flags & IOF_FLUSH)
  3403.         (void)fflush(ed->fp);
  3404.     str_set(ed->str, Yes);
  3405.     STABSET(ed->str);
  3406.     break;
  3407.     case O_DBMOPEN:
  3408. #ifdef SOME_DBM
  3409.     ed->anum = ed->arg[1].arg_type & A_MASK;
  3410.     if (ed->anum == A_WORD || ed->anum == A_STAB)
  3411.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  3412.     else
  3413.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  3414.     if (ed->st[3]->str_nok || ed->st[3]->str_pok)
  3415.         ed->anum = (int)str_gnum(ed->st[3]);
  3416.     else
  3417.         ed->anum = -1;
  3418.     ed->value = (double)hdbmopen(stab_hash(ed->stab),str_get(ed->st[2]),ed->anum);
  3419.     goto donumset;
  3420. #else
  3421.     fatal("No dbm or ndbm on this machine");
  3422. #endif
  3423.     case O_DBMCLOSE:
  3424. #ifdef SOME_DBM
  3425.     if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  3426.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  3427.     else
  3428.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  3429.     hdbmclose(stab_hash(ed->stab));
  3430.     goto say_yes;
  3431. #else
  3432.     fatal("No dbm or ndbm on this machine");
  3433. #endif
  3434.     case O_OPEN:
  3435.     if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  3436.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  3437.     else
  3438.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  3439.     ed->tmps = str_get(ed->st[2]);
  3440.     if (do_open(ed->stab,ed->tmps,ed->st[2]->str_cur)) {
  3441.         ed->value = (double)forkprocess;
  3442.         stab_io(ed->stab)->lines = 0;
  3443.         goto donumset;
  3444.     }
  3445.     else if (forkprocess == 0)        /* we are a new child */
  3446.         goto say_zero;
  3447.     else
  3448.         goto say_undef;
  3449.     /* break; */
  3450.     case O_TRANS:
  3451.     ed->value = (double) do_trans(ed->str,ed->arg);
  3452.     ed->str = ed->arg->arg_ptr.arg_str;
  3453.     goto donumset;
  3454.     case O_NTRANS:
  3455.     str_set(ed->arg->arg_ptr.arg_str, do_trans(ed->str,ed->arg) == 0 ? Yes : No);
  3456.     ed->str = ed->arg->arg_ptr.arg_str;
  3457.     break;
  3458.     case O_CLOSE:
  3459.     if (ed->maxarg == 0)
  3460.         ed->stab = defoutstab;
  3461.     else if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  3462.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  3463.     else
  3464.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  3465.     str_set(ed->str, do_close(ed->stab,TRUE) ? Yes : No );
  3466.     STABSET(ed->str);
  3467.     break;
  3468.     case O_EACH:
  3469.     ed->sp = do_each(ed->str,stab_hash(ed->arg[1].arg_ptr.arg_stab),
  3470.       ed->gimme,ed->arglast);
  3471.     goto array_return;
  3472.     case O_VALUES:
  3473.     case O_KEYS:
  3474.     ed->sp = do_kv(ed->str,stab_hash(ed->arg[1].arg_ptr.arg_stab), ed->optype,
  3475.       ed->gimme,ed->arglast);
  3476.     goto array_return;
  3477.     case O_LARRAY:
  3478.     ed->str->str_nok = ed->str->str_pok = 0;
  3479.     ed->str->str_u.str_stab = ed->arg[1].arg_ptr.arg_stab;
  3480.     ed->str->str_state = SS_ARY;
  3481.     break;
  3482.     case O_ARRAY:
  3483.     ed->ary = stab_array(ed->arg[1].arg_ptr.arg_stab);
  3484.     ed->maxarg = ed->ary->ary_fill + 1;
  3485.     if (ed->gimme == G_ARRAY) { /* array wanted */
  3486.         ed->sp = ed->arglast[0];
  3487.         ed->st -= ed->sp;
  3488.         if (ed->maxarg > 0 && ed->sp + ed->maxarg > stack->ary_max) {
  3489.         astore(stack,ed->sp + ed->maxarg, Nullstr);
  3490.         ed->st = stack->ary_array;
  3491.         }
  3492.         ed->st += ed->sp;
  3493.         Copy(ed->ary->ary_array, &ed->st[1], ed->maxarg, STR*);
  3494.         ed->sp += ed->maxarg;
  3495.         goto array_return;
  3496.     }
  3497.     else {
  3498.         ed->value = (double)ed->maxarg;
  3499.         goto donumset;
  3500.     }
  3501.     case O_AELEM:
  3502.     ed->anum = ((int)str_gnum(ed->st[2])) - arybase;
  3503.     ed->str = afetch(stab_array(ed->arg[1].arg_ptr.arg_stab),ed->anum,FALSE);
  3504.     break;
  3505.     case O_DELETE:
  3506.     tmpstab = ed->arg[1].arg_ptr.arg_stab;
  3507.     ed->tmps = str_get(ed->st[2]);
  3508.     ed->str = hdelete(stab_hash(tmpstab),ed->tmps,ed->st[2]->str_cur);
  3509.     if (tmpstab == envstab)
  3510.         setenv(ed->tmps,Nullch);
  3511.     if (!ed->str)
  3512.         goto say_undef;
  3513.     break;
  3514.     case O_LHASH:
  3515.     ed->str->str_nok = ed->str->str_pok = 0;
  3516.     ed->str->str_u.str_stab = ed->arg[1].arg_ptr.arg_stab;
  3517.     ed->str->str_state = SS_HASH;
  3518.     break;
  3519.     case O_HASH:
  3520.     if (ed->gimme == G_ARRAY) { /* array wanted */
  3521.         ed->sp = do_kv(ed->str,stab_hash(ed->arg[1].arg_ptr.arg_stab), ed->optype,
  3522.         ed->gimme,ed->arglast);
  3523.         goto array_return;
  3524.     }
  3525.     else {
  3526.         tmpstab = ed->arg[1].arg_ptr.arg_stab;
  3527.         if (!stab_hash(tmpstab)->tbl_fill)
  3528.         goto say_zero;
  3529.         sprintf(buf,"%d/%d",stab_hash(tmpstab)->tbl_fill,
  3530.         stab_hash(tmpstab)->tbl_max+1);
  3531.         str_set(ed->str,buf);
  3532.     }
  3533.     break;
  3534.     case O_HELEM:
  3535.     tmpstab = ed->arg[1].arg_ptr.arg_stab;
  3536.     ed->tmps = str_get(ed->st[2]);
  3537.     ed->str = hfetch(stab_hash(tmpstab),ed->tmps,ed->st[2]->str_cur,FALSE);
  3538.     break;
  3539.     case O_LAELEM:
  3540.     ed->anum = ((int)str_gnum(ed->st[2])) - arybase;
  3541.     ed->str = afetch(stab_array(ed->arg[1].arg_ptr.arg_stab),ed->anum,TRUE);
  3542.     if (!ed->str || ed->str == &str_undef)
  3543.         fatal("Assignment to non-creatable ed->value, subscript %d",ed->anum);
  3544.     break;
  3545.     case O_LHELEM:
  3546.     tmpstab = ed->arg[1].arg_ptr.arg_stab;
  3547.     ed->tmps = str_get(ed->st[2]);
  3548.     ed->anum = ed->st[2]->str_cur;
  3549.     ed->str = hfetch(stab_hash(tmpstab),ed->tmps,ed->anum,TRUE);
  3550.     if (!ed->str || ed->str == &str_undef)
  3551.         fatal("Assignment to non-creatable ed->value, subscript \"%s\"",ed->tmps);
  3552.     if (tmpstab == envstab)        /* heavy wizardry going on here */
  3553.         str_magic(ed->str, tmpstab, 'E', ed->tmps, ed->anum);    /* ed->str is now magic */
  3554.                     /* he threw the brick up into the air */
  3555.     else if (tmpstab == sigstab)
  3556.         str_magic(ed->str, tmpstab, 'S', ed->tmps, ed->anum);
  3557. #ifdef SOME_DBM
  3558.     else if (stab_hash(tmpstab)->tbl_dbm)
  3559.         str_magic(ed->str, tmpstab, 'D', ed->tmps, ed->anum);
  3560. #endif
  3561.     else if (tmpstab == DBline)
  3562.         str_magic(ed->str, tmpstab, 'L', ed->tmps, ed->anum);
  3563.     break;
  3564.     case O_LSLICE:
  3565.     ed->anum = 2;
  3566.     ed->argtype = FALSE;
  3567.     goto do_slice_already;
  3568.     case O_ASLICE:
  3569.     ed->anum = 1;
  3570.     ed->argtype = FALSE;
  3571.     goto do_slice_already;
  3572.     case O_HSLICE:
  3573.     ed->anum = 0;
  3574.     ed->argtype = FALSE;
  3575.     goto do_slice_already;
  3576.     case O_LASLICE:
  3577.     ed->anum = 1;
  3578.     ed->argtype = TRUE;
  3579.     goto do_slice_already;
  3580.     case O_LHSLICE:
  3581.     ed->anum = 0;
  3582.     ed->argtype = TRUE;
  3583.       do_slice_already:
  3584.     ed->sp = do_slice(ed->arg[1].arg_ptr.arg_stab,ed->str,ed->anum,ed->argtype,
  3585.         ed->gimme,ed->arglast);
  3586.     goto array_return;
  3587.     case O_SPLICE:
  3588.     ed->sp = do_splice(stab_array(ed->arg[1].arg_ptr.arg_stab),ed->gimme,ed->arglast);
  3589.     goto array_return;
  3590.     case O_PUSH:
  3591.     if (ed->arglast[2] - ed->arglast[1] != 1)
  3592.         ed->str = do_push(stab_array(ed->arg[1].arg_ptr.arg_stab),ed->arglast);
  3593.     else {
  3594.         ed->str = Str_new(51,0);        /* must copy the ed->str */
  3595.         str_sset(ed->str,ed->st[2]);
  3596.         (void)apush(stab_array(ed->arg[1].arg_ptr.arg_stab),ed->str);
  3597.     }
  3598.     break;
  3599.     case O_POP:
  3600.     ed->str = apop(ed->ary = stab_array(ed->arg[1].arg_ptr.arg_stab));
  3601.     goto staticalization;
  3602.     case O_SHIFT:
  3603.     ed->str = ashift(ed->ary = stab_array(ed->arg[1].arg_ptr.arg_stab));
  3604.       staticalization:
  3605.     if (!ed->str)
  3606.         goto say_undef;
  3607.     if (ed->ary->ary_flags & ARF_REAL)
  3608.         (void)str_2mortal(ed->str);
  3609.     break;
  3610.     case O_UNPACK:
  3611.     ed->sp = do_unpack(ed->str,ed->gimme,ed->arglast);
  3612.     goto array_return;
  3613.     case O_SPLIT:
  3614.     ed->value = str_gnum(ed->st[3]);
  3615.     ed->sp = do_split(ed->str, ed->arg[2].arg_ptr.arg_spat, (int)ed->value,
  3616.       ed->gimme,ed->arglast);
  3617.     goto array_return;
  3618.     case O_LENGTH:
  3619.     if (ed->maxarg < 1)
  3620.         ed->value = (double)str_len(stab_val(defstab));
  3621.     else
  3622.         ed->value = (double)str_len(ed->st[1]);
  3623.     goto donumset;
  3624.     case O_SPRINTF:
  3625.     do_sprintf(ed->str, ed->sp-ed->arglast[0], ed->st+1);
  3626.     break;
  3627.     case O_SUBSTR:
  3628.     ed->anum = ((int)str_gnum(ed->st[2])) - arybase;    /* ed->anum=where to start*/
  3629.     ed->tmps = str_get(ed->st[1]);        /* force conversion to string */
  3630.     /*SUPPRESS 560*/
  3631.     if (ed->argtype = (ed->str == ed->st[1]))
  3632.         ed->str = ed->arg->arg_ptr.arg_str;
  3633.     if (ed->anum < 0)
  3634.         ed->anum += ed->st[1]->str_cur + arybase;
  3635.     if (ed->anum < 0 || ed->anum > ed->st[1]->str_cur)
  3636.         str_nset(ed->str,"",0);
  3637.     else {
  3638.         ed->optype = ed->maxarg < 3 ? ed->st[1]->str_cur : (int)str_gnum(ed->st[3]);
  3639.         if (ed->optype < 0)
  3640.         ed->optype = 0;
  3641.         ed->tmps += ed->anum;
  3642.         ed->anum = ed->st[1]->str_cur - ed->anum;    /* ed->anum=how many bytes left*/
  3643.         if (ed->anum > ed->optype)
  3644.         ed->anum = ed->optype;
  3645.         str_nset(ed->str, ed->tmps, ed->anum);
  3646.         if (ed->argtype) {            /* it's an lvalue! */
  3647.         lstr = (struct lstring*)ed->str;
  3648.         ed->str->str_magic = ed->st[1];
  3649.         ed->st[1]->str_rare = 's';
  3650.         lstr->lstr_offset = ed->tmps - str_get(ed->st[1]); 
  3651.         lstr->lstr_len = ed->anum; 
  3652.         }
  3653.     }
  3654.     break;
  3655.     default:
  3656.         fatal("eval1 was incorrectly split");
  3657.     }
  3658. return R_nojump;
  3659.  
  3660. array_return:
  3661.     return R_array_return;
  3662. say_no:
  3663.     return R_say_no;
  3664. re_eval:
  3665.     return R_re_eval;
  3666. badsock:
  3667.     return R_badsock;
  3668. say_yes:
  3669.     return R_say_yes;
  3670. say_undef:
  3671.     return R_say_undef;
  3672. donumset:
  3673.     return R_donumset;
  3674. say_zero:
  3675.     return R_say_zero;    
  3676. }
  3677.  
  3678. EvalResult eval2(EvalData * ed)
  3679. {
  3680.     switch (ed->optype) {
  3681.     case O_PACK:
  3682.     /*SUPPRESS 701*/
  3683.     (void)do_pack(ed->str,ed->arglast);
  3684.     break;
  3685.     case O_GREP:
  3686.     ed->sp = do_grep(ed->arg,ed->str,ed->gimme,ed->arglast);
  3687.     goto array_return;
  3688.     case O_JOIN:
  3689.     do_join(ed->str,ed->arglast);
  3690.     break;
  3691.     case O_SLT:
  3692.     ed->tmps = str_get(ed->st[1]);
  3693.     ed->value = (double) (str_cmp(ed->st[1],ed->st[2]) < 0);
  3694.     goto donumset;
  3695.     case O_SGT:
  3696.     ed->tmps = str_get(ed->st[1]);
  3697.     ed->value = (double) (str_cmp(ed->st[1],ed->st[2]) > 0);
  3698.     goto donumset;
  3699.     case O_SLE:
  3700.     ed->tmps = str_get(ed->st[1]);
  3701.     ed->value = (double) (str_cmp(ed->st[1],ed->st[2]) <= 0);
  3702.     goto donumset;
  3703.     case O_SGE:
  3704.     ed->tmps = str_get(ed->st[1]);
  3705.     ed->value = (double) (str_cmp(ed->st[1],ed->st[2]) >= 0);
  3706.     goto donumset;
  3707.     case O_SEQ:
  3708.     ed->tmps = str_get(ed->st[1]);
  3709.     ed->value = (double) str_eq(ed->st[1],ed->st[2]);
  3710.     goto donumset;
  3711.     case O_SNE:
  3712.     ed->tmps = str_get(ed->st[1]);
  3713.     ed->value = (double) !str_eq(ed->st[1],ed->st[2]);
  3714.     goto donumset;
  3715.     case O_SCMP:
  3716.     ed->tmps = str_get(ed->st[1]);
  3717.     ed->value = (double) str_cmp(ed->st[1],ed->st[2]);
  3718.     goto donumset;
  3719.     case O_SUBR:
  3720.     ed->sp = do_subr(ed->arg,ed->gimme,ed->arglast);
  3721.     ed->st = stack->ary_array + ed->arglast[0];        /* maybe realloced */
  3722.     goto array_return;
  3723.     case O_DBSUBR:
  3724.     ed->sp = do_subr(ed->arg,ed->gimme,ed->arglast);
  3725.     ed->st = stack->ary_array + ed->arglast[0];        /* maybe realloced */
  3726.     goto array_return;
  3727.     case O_CALLER:
  3728.     ed->sp = do_caller(ed->arg,ed->maxarg,ed->gimme,ed->arglast);
  3729.     ed->st = stack->ary_array + ed->arglast[0];        /* maybe realloced */
  3730.     goto array_return;
  3731.     case O_SORT:
  3732.     ed->sp = do_sort(ed->str,ed->arg,
  3733.       ed->gimme,ed->arglast);
  3734.     goto array_return;
  3735.     case O_REVERSE:
  3736.     if (ed->gimme == G_ARRAY)
  3737.         ed->sp = do_reverse(ed->arglast);
  3738.     else
  3739.         ed->sp = do_sreverse(ed->str, ed->arglast);
  3740.     goto array_return;
  3741.     case O_WARN:
  3742.     if (ed->arglast[2] - ed->arglast[1] != 1) {
  3743.         do_join(ed->str,ed->arglast);
  3744.         ed->tmps = str_get(ed->str);
  3745.     }
  3746.     else {
  3747.         ed->str = ed->st[2];
  3748.         ed->tmps = str_get(ed->st[2]);
  3749.     }
  3750.     if (!ed->tmps || !*ed->tmps)
  3751.         ed->tmps = "Warning: something's wrong";
  3752.     warn("%s",ed->tmps);
  3753.     goto say_yes;
  3754.     case O_DIE:
  3755.     if (ed->arglast[2] - ed->arglast[1] != 1) {
  3756.         do_join(ed->str,ed->arglast);
  3757.         ed->tmps = str_get(ed->str);
  3758.     }
  3759.     else {
  3760.         ed->str = ed->st[2];
  3761.         ed->tmps = str_get(ed->st[2]);
  3762.     }
  3763.     if (!ed->tmps || !*ed->tmps)
  3764.         ed->tmps = "Died";
  3765.     fatal("%s",ed->tmps);
  3766.     goto say_zero;
  3767.     case O_PRTF:
  3768.     case O_PRINT:
  3769.     if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  3770.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  3771.     else
  3772.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  3773.     if (!ed->stab)
  3774.         ed->stab = defoutstab;
  3775.     if (!stab_io(ed->stab)) {
  3776.         if (dowarn)
  3777.         warn("Filehandle never opened");
  3778.         goto say_zero;
  3779.     }
  3780.     if (!(ed->fp = stab_io(ed->stab)->ofp)) {
  3781.         if (dowarn)  {
  3782.         if (stab_io(ed->stab)->ifp)
  3783.             warn("Filehandle opened only for input");
  3784.         else
  3785.             warn("Print on closed filehandle");
  3786.         }
  3787.         goto say_zero;
  3788.     }
  3789.     else {
  3790.         if (ed->optype == O_PRTF || ed->arglast[2] - ed->arglast[1] != 1)
  3791.         ed->value = (double)do_aprint(ed->arg,ed->fp,ed->arglast);
  3792.         else {
  3793.         ed->value = (double)do_print(ed->st[2],ed->fp);
  3794.         if (orslen && ed->optype == O_PRINT)
  3795.             if (fwrite(ors, 1, orslen, ed->fp) == 0)
  3796.             goto say_zero;
  3797.         }
  3798.         if (stab_io(ed->stab)->flags & IOF_FLUSH)
  3799.         if (fflush(ed->fp) == EOF)
  3800.             goto say_zero;
  3801.     }
  3802.     goto donumset;
  3803.     case O_CHDIR:
  3804.     if (ed->maxarg < 1)
  3805.         ed->tmps = Nullch;
  3806.     else
  3807.         ed->tmps = str_get(ed->st[1]);
  3808.     if (!ed->tmps || !*ed->tmps) {
  3809.         ed->tmpstr = hfetch(stab_hash(envstab),"HOME",4,FALSE);
  3810.         ed->tmps = str_get(ed->tmpstr);
  3811.     }
  3812.     if (!ed->tmps || !*ed->tmps) {
  3813.         ed->tmpstr = hfetch(stab_hash(envstab),"LOGDIR",6,FALSE);
  3814.         ed->tmps = str_get(ed->tmpstr);
  3815.     }
  3816.     ed->value = (double)(chdir(ed->tmps) >= 0);
  3817.     goto donumset;
  3818.     case O_EXIT:
  3819.     if (ed->maxarg < 1)
  3820.         ed->anum = 0;
  3821.     else
  3822.         ed->anum = (int)str_gnum(ed->st[1]);
  3823.     exit(ed->anum);
  3824.     goto say_zero;
  3825.     case O_RESET:
  3826.     if (ed->maxarg < 1)
  3827.         ed->tmps = "";
  3828.     else
  3829.         ed->tmps = str_get(ed->st[1]);
  3830.     str_reset(ed->tmps,curcmd->c_stash);
  3831.     ed->value = 1.0;
  3832.     goto donumset;
  3833.     case O_LIST:
  3834.     if (ed->gimme == G_ARRAY)
  3835.         goto array_return;
  3836.     if (ed->maxarg > 0)
  3837.         ed->str = ed->st[ed->sp - ed->arglast[0]];    /* unwanted list, return last item */
  3838.     else
  3839.         ed->str = &str_undef;
  3840.     break;
  3841.     case O_EOF:
  3842.     if (ed->maxarg <= 0)
  3843.         ed->stab = last_in_stab;
  3844.     else if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  3845.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  3846.     else
  3847.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  3848.     str_set(ed->str, do_eof(ed->stab) ? Yes : No);
  3849.     STABSET(ed->str);
  3850.     break;
  3851.     case O_GETC:
  3852.     if (ed->maxarg <= 0)
  3853.         ed->stab = stdinstab;
  3854.     else if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  3855.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  3856.     else
  3857.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  3858.     if (!ed->stab)
  3859.         ed->stab = argvstab;
  3860.     if (!ed->stab || do_eof(ed->stab)) /* make sure we have ed->fp with something */
  3861.         goto say_undef;
  3862.     else {
  3863.         str_set(ed->str," ");
  3864.         *ed->str->str_ptr = getc(stab_io(ed->stab)->ifp); /* should never be EOF */
  3865.     }
  3866.     STABSET(ed->str);
  3867.     break;
  3868.     case O_TELL:
  3869.     if (ed->maxarg <= 0)
  3870.         ed->stab = last_in_stab;
  3871.     else if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  3872.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  3873.     else
  3874.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  3875.     ed->value = (double)do_tell(ed->stab);
  3876.     goto donumset;
  3877.     case O_RECV:
  3878.     case O_READ:
  3879.     case O_SYSREAD:
  3880.     if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  3881.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  3882.     else
  3883.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  3884.     ed->tmps = str_get(ed->st[2]);
  3885.     ed->anum = (int)str_gnum(ed->st[3]);
  3886.     errno = 0;
  3887.     ed->maxarg = ed->sp - ed->arglast[0];
  3888.     if (ed->maxarg > 4)
  3889.         warn("Too many args on read");
  3890.     if (ed->maxarg == 4)
  3891.         ed->maxarg = (int)str_gnum(ed->st[4]);
  3892.     else
  3893.         ed->maxarg = 0;
  3894.     if (!stab_io(ed->stab) || !stab_io(ed->stab)->ifp)
  3895.         goto say_undef;
  3896. #ifdef HAS_SOCKET
  3897.     if (ed->optype == O_RECV) {
  3898.         ed->argtype = sizeof buf;
  3899.         STR_GROW(ed->st[2], ed->anum+1), (ed->tmps = str_get(ed->st[2]));  /* sneaky */
  3900.         ed->anum = recvfrom(fileno(stab_io(ed->stab)->ifp), ed->tmps, ed->anum, ed->maxarg,
  3901.         buf, &ed->argtype);
  3902.         if (ed->anum >= 0) {
  3903.         ed->st[2]->str_cur = ed->anum;
  3904.         ed->st[2]->str_ptr[ed->anum] = '\0';
  3905.         str_nset(ed->str,buf,ed->argtype);
  3906.         }
  3907.         else
  3908.         str_sset(ed->str,&str_undef);
  3909.         break;
  3910.     }
  3911. #else
  3912.     if (ed->optype == O_RECV)
  3913.         goto badsock;
  3914. #endif
  3915.     STR_GROW(ed->st[2], ed->anum+ed->maxarg+1), (ed->tmps = str_get(ed->st[2]));  /* sneaky */
  3916.     if (ed->optype == O_SYSREAD) {
  3917.         ed->anum = read(fileno(stab_io(ed->stab)->ifp), ed->tmps+ed->maxarg, ed->anum);
  3918.     }
  3919.     else
  3920. #ifdef HAS_SOCKET
  3921.     if (stab_io(ed->stab)->type == 's') {
  3922.         ed->argtype = sizeof buf;
  3923.         ed->anum = recvfrom(fileno(stab_io(ed->stab)->ifp), ed->tmps+ed->maxarg, ed->anum, 0,
  3924.         buf, &ed->argtype);
  3925.     }
  3926.     else
  3927. #endif
  3928.         ed->anum = fread(ed->tmps+ed->maxarg, 1, ed->anum, stab_io(ed->stab)->ifp);
  3929.     if (ed->anum < 0)
  3930.         goto say_undef;
  3931.     ed->st[2]->str_cur = ed->anum+ed->maxarg;
  3932.     ed->st[2]->str_ptr[ed->anum+ed->maxarg] = '\0';
  3933.     ed->value = (double)ed->anum;
  3934.     goto donumset;
  3935.     case O_SYSWRITE:
  3936.     case O_SEND:
  3937.     if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  3938.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  3939.     else
  3940.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  3941.     ed->tmps = str_get(ed->st[2]);
  3942.     ed->anum = (int)str_gnum(ed->st[3]);
  3943.     errno = 0;
  3944.     stio = stab_io(ed->stab);
  3945.     ed->maxarg = ed->sp - ed->arglast[0];
  3946.     if (!stio || !stio->ifp) {
  3947.         ed->anum = -1;
  3948.         if (dowarn) {
  3949.         if (ed->optype == O_SYSWRITE)
  3950.             warn("Syswrite on closed filehandle");
  3951.         else
  3952.             warn("Send on closed socket");
  3953.         }
  3954.     }
  3955.     else if (ed->optype == O_SYSWRITE) {
  3956.         if (ed->maxarg > 4)
  3957.         warn("Too many args on syswrite");
  3958.         if (ed->maxarg == 4)
  3959.         ed->optype = (int)str_gnum(ed->st[4]);
  3960.         else
  3961.         ed->optype = 0;
  3962.         ed->anum = write(fileno(stab_io(ed->stab)->ifp), ed->tmps+ed->optype, ed->anum);
  3963.     }
  3964. #ifdef HAS_SOCKET
  3965.     else if (ed->maxarg >= 4) {
  3966.         if (ed->maxarg > 4)
  3967.         warn("Too many args on send");
  3968.         ed->tmps2 = str_get(ed->st[4]);
  3969.         ed->anum = sendto(fileno(stab_io(ed->stab)->ifp), ed->tmps, ed->st[2]->str_cur,
  3970.           ed->anum, ed->tmps2, ed->st[4]->str_cur);
  3971.     }
  3972.     else
  3973.         ed->anum = send(fileno(stab_io(ed->stab)->ifp), ed->tmps, ed->st[2]->str_cur, ed->anum);
  3974. #else
  3975.     else
  3976.         goto badsock;
  3977. #endif
  3978.     if (ed->anum < 0)
  3979.         goto say_undef;
  3980.     ed->value = (double)ed->anum;
  3981.     goto donumset;
  3982.     case O_SEEK:
  3983.     if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  3984.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  3985.     else
  3986.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  3987.     ed->value = str_gnum(ed->st[2]);
  3988.     str_set(ed->str, do_seek(ed->stab,
  3989.       (long)ed->value, (int)str_gnum(ed->st[3]) ) ? Yes : No);
  3990.     STABSET(ed->str);
  3991.     break;
  3992.     case O_RETURN:
  3993.     ed->tmps = "_SUB_";        /* just fake up a "last _SUB_" */
  3994.     ed->optype = O_LAST;
  3995.     if (curcsv && curcsv->wantarray == G_ARRAY) {
  3996.         lastretstr = Nullstr;
  3997.         lastspbase = ed->arglast[1];
  3998.         lastsize = ed->arglast[2] - ed->arglast[1];
  3999.     }
  4000.     else
  4001.         lastretstr = str_mortal(ed->st[ed->arglast[2] - ed->arglast[0]]);
  4002.     goto dopop;
  4003.     case O_REDO:
  4004.     case O_NEXT:
  4005.     case O_LAST:
  4006.     ed->tmps = Nullch;
  4007.     if (ed->maxarg > 0) {
  4008.         ed->tmps = str_get(ed->arg[1].arg_ptr.arg_str);
  4009.       dopop:
  4010.         while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
  4011.           strNE(ed->tmps,loop_stack[loop_ptr].loop_label) )) {
  4012. #ifdef DEBUGGING
  4013.         if (debug & 4) {
  4014.             deb("(Skipping label #%d %s)\n",loop_ptr,
  4015.             loop_stack[loop_ptr].loop_label);
  4016.         }
  4017. #endif
  4018.         loop_ptr--;
  4019.         }
  4020. #ifdef DEBUGGING
  4021.         if (debug & 4) {
  4022.         deb("(Found label #%d %s)\n",loop_ptr,
  4023.             loop_stack[loop_ptr].loop_label);
  4024.         }
  4025. #endif
  4026.     }
  4027.     if (loop_ptr < 0) {
  4028.         if (ed->tmps && strEQ(ed->tmps, "_SUB_"))
  4029.         fatal("Can't return outside a subroutine");
  4030.         fatal("Bad label: %s", ed->maxarg > 0 ? ed->tmps : "<null>");
  4031.     }
  4032.     if (!lastretstr && ed->optype == O_LAST && lastsize) {
  4033.         ed->st -= ed->arglast[0];
  4034.         ed->st += lastspbase + 1;
  4035.         ed->optype = loop_stack[loop_ptr].loop_sp - lastspbase; /* negative */
  4036.         if (ed->optype) {
  4037.         for (ed->anum = lastsize; ed->anum > 0; ed->anum--,ed->st++)
  4038.             ed->st[ed->optype] = str_mortal(ed->st[0]);
  4039.         }
  4040.         longjmp(loop_stack[loop_ptr].loop_env, O_LAST);
  4041.     }
  4042.     longjmp(loop_stack[loop_ptr].loop_env, ed->optype);
  4043.     case O_DUMP:
  4044.     case O_GOTO:/* shudder */
  4045.     goto_targ = str_get(ed->arg[1].arg_ptr.arg_str);
  4046.     if (!*goto_targ)
  4047.         goto_targ = Nullch;        /* just restart from top */
  4048.     if (ed->optype == O_DUMP) {
  4049.         do_undump = 1;
  4050.         my_unexec();
  4051.     }
  4052.     longjmp(top_env, 1);
  4053.     case O_INDEX:
  4054.     ed->tmps = str_get(ed->st[1]);
  4055.     if (ed->maxarg < 3)
  4056.         ed->anum = 0;
  4057.     else {
  4058.         ed->anum = (int) str_gnum(ed->st[3]) - arybase;
  4059.         if (ed->anum < 0)
  4060.         ed->anum = 0;
  4061.         else if (ed->anum > ed->st[1]->str_cur)
  4062.         ed->anum = ed->st[1]->str_cur;
  4063.     }
  4064.     if (!(ed->tmps2 = fbminstr((unsigned char*)ed->tmps + ed->anum,
  4065.       (unsigned char*)ed->tmps + ed->st[1]->str_cur, ed->st[2])))
  4066.         ed->value = (double)(-1 + arybase);
  4067.     else
  4068.         ed->value = (double)(ed->tmps2 - ed->tmps + arybase);
  4069.     goto donumset;
  4070.     case O_RINDEX:
  4071.     ed->tmps = str_get(ed->st[1]);
  4072.     ed->tmps2 = str_get(ed->st[2]);
  4073.     if (ed->maxarg < 3)
  4074.         ed->anum = ed->st[1]->str_cur;
  4075.     else {
  4076.         ed->anum = (int) str_gnum(ed->st[3]) - arybase + ed->st[2]->str_cur;
  4077.         if (ed->anum < 0)
  4078.         ed->anum = 0;
  4079.         else if (ed->anum > ed->st[1]->str_cur)
  4080.         ed->anum = ed->st[1]->str_cur;
  4081.     }
  4082.     if (!(ed->tmps2 = rninstr(ed->tmps,  ed->tmps  + ed->anum,
  4083.                   ed->tmps2, ed->tmps2 + ed->st[2]->str_cur)))
  4084.         ed->value = (double)(-1 + arybase);
  4085.     else
  4086.         ed->value = (double)(ed->tmps2 - ed->tmps + arybase);
  4087.     goto donumset;
  4088.     case O_TIME:
  4089.     ed->value = (double) time(Null(time_t*));
  4090.     goto donumset;
  4091.     case O_TMS:
  4092.     ed->sp = do_tms(ed->str,ed->gimme,ed->arglast);
  4093.     goto array_return;
  4094.     case O_LOCALTIME:
  4095.     if (ed->maxarg < 1)
  4096.         (void)time(&ed->when);
  4097.     else
  4098.         ed->when = (time_t)str_gnum(ed->st[1]);
  4099.     ed->sp = do_time(ed->str,localtime(&ed->when),
  4100.       ed->gimme,ed->arglast);
  4101.     goto array_return;
  4102.     case O_GMTIME:
  4103.     if (ed->maxarg < 1)
  4104.         (void)time(&ed->when);
  4105.     else
  4106.         ed->when = (time_t)str_gnum(ed->st[1]);
  4107.     ed->sp = do_time(ed->str,gmtime(&ed->when),
  4108.       ed->gimme,ed->arglast);
  4109.     goto array_return;
  4110.     case O_TRUNCATE:
  4111.     ed->sp = do_truncate(ed->str,ed->arg,
  4112.       ed->gimme,ed->arglast);
  4113.     goto array_return;
  4114.     case O_LSTAT:
  4115.     case O_STAT:
  4116.     ed->sp = do_stat(ed->str,ed->arg,
  4117.       ed->gimme,ed->arglast);
  4118.     goto array_return;
  4119.     case O_CRYPT:
  4120. #ifdef HAS_CRYPT
  4121.     ed->tmps = str_get(ed->st[1]);
  4122. #ifdef FCRYPT
  4123.     str_set(ed->str,fcrypt(ed->tmps,str_get(ed->st[2])));
  4124. #else
  4125.     str_set(ed->str,crypt(ed->tmps,str_get(ed->st[2])));
  4126. #endif
  4127. #else
  4128.     fatal(
  4129.       "The crypt() function is unimplemented due to excessive paranoia.");
  4130. #endif
  4131.     break;
  4132.     case O_ATAN2:
  4133.     ed->value = str_gnum(ed->st[1]);
  4134.     ed->value = atan2(ed->value,str_gnum(ed->st[2]));
  4135.     goto donumset;
  4136.     case O_SIN:
  4137.     if (ed->maxarg < 1)
  4138.         ed->value = str_gnum(stab_val(defstab));
  4139.     else
  4140.         ed->value = str_gnum(ed->st[1]);
  4141.     ed->value = sin(ed->value);
  4142.     goto donumset;
  4143.     case O_COS:
  4144.     if (ed->maxarg < 1)
  4145.         ed->value = str_gnum(stab_val(defstab));
  4146.     else
  4147.         ed->value = str_gnum(ed->st[1]);
  4148.     ed->value = cos(ed->value);
  4149.     goto donumset;
  4150.     case O_RAND:
  4151.     if (ed->maxarg < 1)
  4152.         ed->value = 1.0;
  4153.     else
  4154.         ed->value = str_gnum(ed->st[1]);
  4155.     if (ed->value == 0.0)
  4156.         ed->value = 1.0;
  4157. #if RANDBITS == 31
  4158.     ed->value = rand() * ed->value / 2147483648.0;
  4159. #else
  4160. #if RANDBITS == 16
  4161.     ed->value = rand() * ed->value / 65536.0;
  4162. #else
  4163. #if RANDBITS == 15
  4164.     ed->value = rand() * ed->value / 32768.0;
  4165. #else
  4166.     ed->value = rand() * ed->value / (double)(((unsigned long)1) << RANDBITS);
  4167. #endif
  4168. #endif
  4169. #endif
  4170.     goto donumset;
  4171.     case O_SRAND:
  4172.     if (ed->maxarg < 1) {
  4173.         (void)time(&ed->when);
  4174.         ed->anum = ed->when;
  4175.     }
  4176.     else
  4177.         ed->anum = (int)str_gnum(ed->st[1]);
  4178.     srand(ed->anum);
  4179.     goto say_yes;
  4180.     case O_EXP:
  4181.     if (ed->maxarg < 1)
  4182.         ed->value = str_gnum(stab_val(defstab));
  4183.     else
  4184.         ed->value = str_gnum(ed->st[1]);
  4185.     ed->value = exp(ed->value);
  4186.     goto donumset;
  4187.     case O_LOG:
  4188.     if (ed->maxarg < 1)
  4189.         ed->value = str_gnum(stab_val(defstab));
  4190.     else
  4191.         ed->value = str_gnum(ed->st[1]);
  4192.     if (ed->value <= 0.0)
  4193.         fatal("Can't take log of %g\n", ed->value);
  4194.     ed->value = log(ed->value);
  4195.     goto donumset;
  4196.     case O_SQRT:
  4197.     if (ed->maxarg < 1)
  4198.         ed->value = str_gnum(stab_val(defstab));
  4199.     else
  4200.         ed->value = str_gnum(ed->st[1]);
  4201.     if (ed->value < 0.0)
  4202.         fatal("Can't take sqrt of %g\n", ed->value);
  4203.     ed->value = sqrt(ed->value);
  4204.     goto donumset;
  4205.     case O_INT:
  4206.     if (ed->maxarg < 1)
  4207.         ed->value = str_gnum(stab_val(defstab));
  4208.     else
  4209.         ed->value = str_gnum(ed->st[1]);
  4210.     {
  4211.          extended    intpart;
  4212.         
  4213.         if (ed->value >= 0.0)
  4214.             (void)modf(ed->value,&intpart);
  4215.         else {
  4216.             (void)modf(-ed->value,&intpart);
  4217.             intpart = -intpart;
  4218.         }
  4219.         
  4220.         ed->value = intpart;
  4221.     }
  4222.     goto donumset;
  4223.     case O_ORD:
  4224.     if (ed->maxarg < 1)
  4225.         ed->tmps = str_get(stab_val(defstab));
  4226.     else
  4227.         ed->tmps = str_get(ed->st[1]);
  4228.     ed->value = (double) (*ed->tmps & 255);
  4229.     goto donumset;
  4230.     case O_ALARM:
  4231. #ifdef HAS_ALARM
  4232.     if (ed->maxarg < 1)
  4233.         ed->tmps = str_get(stab_val(defstab));
  4234.     else
  4235.         ed->tmps = str_get(ed->st[1]);
  4236.     if (!ed->tmps)
  4237.         ed->tmps = "0";
  4238.     ed->anum = alarm((unsigned int)atoi(ed->tmps));
  4239.     if (ed->anum < 0)
  4240.         goto say_undef;
  4241.     ed->value = (double)ed->anum;
  4242.     goto donumset;
  4243. #else
  4244.     fatal("Unsupported function alarm");
  4245.     break;
  4246. #endif
  4247.     case O_SLEEP:
  4248.     if (ed->maxarg < 1)
  4249.         ed->tmps = Nullch;
  4250.     else
  4251.         ed->tmps = str_get(ed->st[1]);
  4252.     (void)time(&ed->when);
  4253.     if (!ed->tmps || !*ed->tmps)
  4254.         sleep((32767<<16)+32767);
  4255.     else
  4256.         sleep((unsigned int)atoi(ed->tmps));
  4257.     ed->value = (double)ed->when;
  4258.     (void)time(&ed->when);
  4259.     ed->value = ((double)ed->when) - ed->value;
  4260.     goto donumset;
  4261.     case O_RANGE:
  4262.     ed->sp = do_range(ed->gimme,ed->arglast);
  4263.     goto array_return;
  4264.     case O_F_OR_R:
  4265.     if (ed->gimme == G_ARRAY) {        /* it's a range */
  4266.         /* can we optimize to constant array? */
  4267.         if ((ed->arg[1].arg_type & A_MASK) == A_SINGLE &&
  4268.           (ed->arg[2].arg_type & A_MASK) == A_SINGLE) {
  4269.         ed->st[2] = ed->arg[2].arg_ptr.arg_str;
  4270.         ed->sp = do_range(ed->gimme,ed->arglast);
  4271.         ed->st = stack->ary_array;
  4272.         ed->maxarg = ed->sp - ed->arglast[0];
  4273.         str_free(ed->arg[1].arg_ptr.arg_str);
  4274.         ed->arg[1].arg_ptr.arg_str = Nullstr;
  4275.         str_free(ed->arg[2].arg_ptr.arg_str);
  4276.         ed->arg[2].arg_ptr.arg_str = Nullstr;
  4277.         ed->arg->arg_type = O_ARRAY;
  4278.         ed->arg[1].arg_type = A_STAB|A_DONT;
  4279.         ed->arg->arg_len = 1;
  4280.         ed->stab = ed->arg[1].arg_ptr.arg_stab = aadd(genstab());
  4281.         ed->ary = stab_array(ed->stab);
  4282.         afill(ed->ary,ed->maxarg - 1);
  4283.         ed->anum = ed->maxarg;
  4284.         ed->st += ed->arglast[0]+1;
  4285.         while (ed->maxarg-- > 0)
  4286.             ed->ary->ary_array[ed->maxarg] = str_smake(ed->st[ed->maxarg]);
  4287.         ed->st -= ed->arglast[0]+1;
  4288.         goto array_return;
  4289.         }
  4290.         ed->arg->arg_type = ed->optype = O_RANGE;
  4291.         ed->maxarg = ed->arg->arg_len = 2;
  4292.         ed->anum = 2;
  4293.         ed->arg[ed->anum].arg_flags &= ~AF_ARYOK;
  4294.         ed->argflags = ed->arg[ed->anum].arg_flags;
  4295.         ed->argtype = ed->arg[ed->anum].arg_type & A_MASK;
  4296.         ed->arg[ed->anum].arg_type = ed->argtype;
  4297.         ed->argptr = ed->arg[ed->anum].arg_ptr;
  4298.         ed->sp = ed->arglast[0];
  4299.         ed->st -= ed->sp;
  4300.         ed->sp++;
  4301.         goto re_eval;
  4302.     }
  4303.     ed->arg->arg_type = O_FLIP;
  4304.     /* FALL THROUGH */
  4305.     case O_FLIP:
  4306.     if ((ed->arg[1].arg_type & A_MASK) == A_SINGLE ?
  4307.       last_in_stab && (int)str_gnum(ed->st[1]) == stab_io(last_in_stab)->lines
  4308.       :
  4309.       str_true(ed->st[1]) ) {
  4310.         str_numset(ed->str,0.0);
  4311.         ed->anum = 2;
  4312.         ed->arg->arg_type = ed->optype = O_FLOP;
  4313.         ed->arg[2].arg_type &= ~A_DONT;
  4314.         ed->arg[1].arg_type |= A_DONT;
  4315.         ed->argflags = ed->arg[2].arg_flags;
  4316.         ed->argtype = ed->arg[2].arg_type & A_MASK;
  4317.         ed->argptr = ed->arg[2].arg_ptr;
  4318.         ed->sp = ed->arglast[0];
  4319.         ed->st -= ed->sp++;
  4320.         goto re_eval;
  4321.     }
  4322.     str_set(ed->str,"");
  4323.     break;
  4324.     case O_FLOP:
  4325.     str_inc(ed->str);
  4326.     if ((ed->arg[2].arg_type & A_MASK) == A_SINGLE ?
  4327.       last_in_stab && (int)str_gnum(ed->st[2]) == stab_io(last_in_stab)->lines
  4328.       :
  4329.       str_true(ed->st[2]) ) {
  4330.         ed->arg->arg_type = O_FLIP;
  4331.         ed->arg[1].arg_type &= ~A_DONT;
  4332.         ed->arg[2].arg_type |= A_DONT;
  4333.         str_cat(ed->str,"E0");
  4334.     }
  4335.     break;
  4336.     case O_FORK:
  4337.     fatal("Unsupported function fork");
  4338.     break;
  4339.     case O_WAIT:
  4340.     fatal("Unsupported function wait");
  4341.     break;
  4342.     case O_WAITPID:
  4343.     fatal("Unsupported function wait");
  4344.     break;
  4345.     case O_SYSTEM:
  4346.     if ((ed->arg[1].arg_type & A_MASK) == A_STAB)
  4347.         ed->value = (double)do_aspawn(ed->st[1],ed->arglast);
  4348.     else if (ed->arglast[2] - ed->arglast[1] != 1)
  4349.         ed->value = (double)do_aspawn(Nullstr,ed->arglast);
  4350.     else {
  4351.         ed->value = (double)do_spawn(str_get(str_mortal(ed->st[2])));
  4352.     }
  4353.     goto donumset;
  4354.     case O_EXEC_OP:
  4355.     if ((ed->arg[1].arg_type & A_MASK) == A_STAB)
  4356.         ed->value = (double)do_aexec(ed->st[1],ed->arglast);
  4357.     else if (ed->arglast[2] - ed->arglast[1] != 1)
  4358.         ed->value = (double)do_aexec(Nullstr,ed->arglast);
  4359.     else {
  4360.         ed->value = (double)do_exec(str_get(str_mortal(ed->st[2])));
  4361.     }
  4362.     goto donumset;
  4363.     case O_HEX:
  4364.     if (ed->maxarg < 1)
  4365.         ed->tmps = str_get(stab_val(defstab));
  4366.     else
  4367.         ed->tmps = str_get(ed->st[1]);
  4368.     ed->value = (double)scanhex(ed->tmps, 99, &ed->argtype);
  4369.     goto donumset;
  4370.  
  4371.     case O_OCT:
  4372.     if (ed->maxarg < 1)
  4373.         ed->tmps = str_get(stab_val(defstab));
  4374.     else
  4375.         ed->tmps = str_get(ed->st[1]);
  4376.     while (*ed->tmps && (isSPACE(*ed->tmps) || *ed->tmps == '0'))
  4377.         ed->tmps++;
  4378.     if (*ed->tmps == 'x')
  4379.         ed->value = (double)scanhex(++ed->tmps, 99, &ed->argtype);
  4380.     else
  4381.         ed->value = (double)scanoct(ed->tmps, 99, &ed->argtype);
  4382.     goto donumset;
  4383.     default:
  4384.     fatal("eval2 was incorrectly split");
  4385.     }
  4386. return R_nojump;
  4387.  
  4388. array_return:
  4389.     return R_array_return;
  4390. say_no:
  4391.     return R_say_no;
  4392. re_eval:
  4393.     return R_re_eval;
  4394. badsock:
  4395.     return R_badsock;
  4396. say_yes:
  4397.     return R_say_yes;
  4398. say_undef:
  4399.     return R_say_undef;
  4400. donumset:
  4401.     return R_donumset;
  4402. say_zero:
  4403.     return R_say_zero;    
  4404. }
  4405.  
  4406. int
  4407. eval(arg,gimme,sp)
  4408. register ARG *arg;
  4409. int gimme;
  4410. register int sp;
  4411. {
  4412.     EvalData    edt;
  4413.     EvalData *    ed;
  4414.     
  4415.     ed                =    &edt;
  4416.     ed->arg            =    arg;
  4417.     ed->gimme        =    gimme;
  4418.     ed->sp            =    sp;
  4419.     ed->assigning    =    FALSE;
  4420.     
  4421.     if (!ed->arg)
  4422.     goto say_undef;
  4423.     ed->optype = ed->arg->arg_type;
  4424.     ed->maxarg = ed->arg->arg_len;
  4425.     ed->arglast[0] = ed->sp;
  4426.     ed->str = ed->arg->arg_ptr.arg_str;
  4427.     if (ed->sp + ed->maxarg > stack->ary_max)
  4428.     astore(stack, ed->sp + ed->maxarg, Nullstr);
  4429.     ed->st = stack->ary_array;
  4430.  
  4431. #ifdef DEBUGGING
  4432.     if (debug) {
  4433.     if (debug & 8) {
  4434.         deb("%s (%lx) %d args:\n",opname[ed->optype],ed->arg,ed->maxarg);
  4435.     }
  4436.     debname[dlevel] = opname[ed->optype][0];
  4437.     debdelim[dlevel] = ':';
  4438.     if (++dlevel >= dlmax)
  4439.         grow_dlevel();
  4440.     }
  4441. #endif
  4442.  
  4443.     for (ed->anum = 1; ed->anum <= ed->maxarg; ed->anum++) {
  4444.     ed->argflags = ed->arg[ed->anum].arg_flags;
  4445.     ed->argtype = ed->arg[ed->anum].arg_type;
  4446.     ed->argptr = ed->arg[ed->anum].arg_ptr;
  4447.       re_eval:
  4448.     switch (ed->argtype) {
  4449.     default:
  4450.         ed->st[++ed->sp] = &str_undef;
  4451. #ifdef DEBUGGING
  4452.         ed->tmps = "NULL";
  4453. #endif
  4454.         break;
  4455.     case A_EXPR:
  4456. #ifdef DEBUGGING
  4457.         if (debug & 8) {
  4458.         ed->tmps = "EXPR";
  4459.         deb("%d.EXPR =>\n",ed->anum);
  4460.         }
  4461. #endif
  4462.         ed->sp = eval(ed->argptr.arg_arg,
  4463.         (ed->argflags & AF_ARYOK) ? G_ARRAY : G_SCALAR, ed->sp);
  4464.         if (ed->sp + (ed->maxarg - ed->anum) > stack->ary_max)
  4465.         astore(stack, ed->sp + (ed->maxarg - ed->anum), Nullstr);
  4466.         ed->st = stack->ary_array;    /* possibly reallocated */
  4467.         break;
  4468.         case A_CMD:
  4469. #ifdef DEBUGGING
  4470.         if (debug & 8) {
  4471.         ed->tmps = "CMD";
  4472.         deb("%d.CMD (%lx) =>\n",ed->anum,ed->argptr.arg_cmd);
  4473.         }
  4474. #endif
  4475.         ed->sp = cmd_exec(ed->argptr.arg_cmd, ed->gimme, ed->sp);
  4476.         if (ed->sp + (ed->maxarg - ed->anum) > stack->ary_max)
  4477.         astore(stack, ed->sp + (ed->maxarg - ed->anum), Nullstr);
  4478.         ed->st = stack->ary_array;    /* possibly reallocated */
  4479.         break;
  4480.         case A_LARYSTAB:
  4481.         ++ed->sp;
  4482.         switch (ed->optype) {
  4483.         case O_ITEM2: ed->argtype = 2; break;
  4484.         case O_ITEM3: ed->argtype = 3; break;
  4485.         default:      ed->argtype = ed->anum; break;
  4486.         }
  4487.         ed->str = afetch(stab_array(ed->argptr.arg_stab),
  4488.         ed->arg[ed->argtype].arg_len - arybase, TRUE);
  4489. #ifdef DEBUGGING
  4490.         if (debug & 8) {
  4491.         (void)sprintf(buf,"LARYSTAB $%s[%d]",stab_name(ed->argptr.arg_stab),
  4492.             ed->arg[ed->argtype].arg_len);
  4493.         ed->tmps = buf;
  4494.         }
  4495. #endif
  4496.         goto do_crement;
  4497.         case A_ARYSTAB:
  4498.         switch (ed->optype) {
  4499.         case O_ITEM2: ed->argtype = 2; break;
  4500.         case O_ITEM3: ed->argtype = 3; break;
  4501.         default:      ed->argtype = ed->anum; break;
  4502.         }
  4503.         ed->st[++ed->sp] = afetch(stab_array(ed->argptr.arg_stab),
  4504.         ed->arg[ed->argtype].arg_len - arybase, FALSE);
  4505. #ifdef DEBUGGING
  4506.         if (debug & 8) {
  4507.         (void)sprintf(buf,"ARYSTAB $%s[%d]",stab_name(ed->argptr.arg_stab),
  4508.             ed->arg[ed->argtype].arg_len);
  4509.         ed->tmps = buf;
  4510.         }
  4511. #endif
  4512.         break;
  4513.     case A_STAR:
  4514.         ed->stab = ed->argptr.arg_stab;
  4515.         ed->st[++ed->sp] = (STR*)ed->stab;
  4516.         if (!stab_xarray(ed->stab))
  4517.         aadd(ed->stab);
  4518.         if (!stab_xhash(ed->stab))
  4519.         hadd(ed->stab);
  4520.         if (!stab_io(ed->stab))
  4521.         stab_io(ed->stab) = stio_new();
  4522. #ifdef DEBUGGING
  4523.         if (debug & 8) {
  4524.         (void)sprintf(buf,"STAR *%s",stab_name(ed->argptr.arg_stab));
  4525.         ed->tmps = buf;
  4526.         }
  4527. #endif
  4528.         break;
  4529.     case A_LSTAR:
  4530.         ed->str = ed->st[++ed->sp] = (STR*)ed->argptr.arg_stab;
  4531. #ifdef DEBUGGING
  4532.         if (debug & 8) {
  4533.         (void)sprintf(buf,"LSTAR *%s",stab_name(ed->argptr.arg_stab));
  4534.         ed->tmps = buf;
  4535.         }
  4536. #endif
  4537.         break;
  4538.     case A_STAB:
  4539.         ed->st[++ed->sp] = STAB_STR(ed->argptr.arg_stab);
  4540. #ifdef DEBUGGING
  4541.         if (debug & 8) {
  4542.         (void)sprintf(buf,"STAB $%s",stab_name(ed->argptr.arg_stab));
  4543.         ed->tmps = buf;
  4544.         }
  4545. #endif
  4546.         break;
  4547.     case A_LENSTAB:
  4548.         str_numset(ed->str, (double)STAB_LEN(ed->argptr.arg_stab));
  4549.         ed->st[++ed->sp] = ed->str;
  4550. #ifdef DEBUGGING
  4551.         if (debug & 8) {
  4552.         (void)sprintf(buf,"LENSTAB $%s",stab_name(argptr.arg_stab));
  4553.         tmps = buf;
  4554.         }
  4555. #endif
  4556.         break;
  4557.     case A_LEXPR:
  4558. #ifdef DEBUGGING
  4559.         if (debug & 8) {
  4560.         ed->tmps = "LEXPR";
  4561.         deb("%d.LEXPR =>\n",ed->anum);
  4562.         }
  4563. #endif
  4564.         if (ed->argflags & AF_ARYOK) {
  4565.         ed->sp = eval(ed->argptr.arg_arg, G_ARRAY, ed->sp);
  4566.         if (ed->sp + (ed->maxarg - ed->anum) > stack->ary_max)
  4567.             astore(stack, ed->sp + (ed->maxarg - ed->anum), Nullstr);
  4568.         ed->st = stack->ary_array;    /* possibly reallocated */
  4569.         }
  4570.         else {
  4571.         ed->sp = eval(ed->argptr.arg_arg, G_SCALAR, ed->sp);
  4572.         ed->st = stack->ary_array;    /* possibly reallocated */
  4573.         ed->str = ed->st[ed->sp];
  4574.         goto do_crement;
  4575.         }
  4576.         break;
  4577.     case A_LVAL:
  4578. #ifdef DEBUGGING
  4579.         if (debug & 8) {
  4580.         (void)sprintf(buf,"LVAL $%s",stab_name(ed->argptr.arg_stab));
  4581.         ed->tmps = buf;
  4582.         }
  4583. #endif
  4584.         ++ed->sp;
  4585.         ed->str = STAB_STR(ed->argptr.arg_stab);
  4586.         if (!ed->str)
  4587.         fatal("panic: A_LVAL");
  4588.       do_crement:
  4589.         ed->assigning = TRUE;
  4590.         if (ed->argflags & AF_PRE) {
  4591.         if (ed->argflags & AF_UP)
  4592.             str_inc(ed->str);
  4593.         else
  4594.             str_dec(ed->str);
  4595.         STABSET(ed->str);
  4596.         ed->st[ed->sp] = ed->str;
  4597.         ed->str = ed->arg->arg_ptr.arg_str;
  4598.         }
  4599.         else if (ed->argflags & AF_POST) {
  4600.         ed->st[ed->sp] = str_mortal(ed->str);
  4601.         if (ed->argflags & AF_UP)
  4602.             str_inc(ed->str);
  4603.         else
  4604.             str_dec(ed->str);
  4605.         STABSET(ed->str);
  4606.         ed->str = ed->arg->arg_ptr.arg_str;
  4607.         }
  4608.         else
  4609.         ed->st[ed->sp] = ed->str;
  4610.         break;
  4611.     case A_LARYLEN:
  4612.         ++ed->sp;
  4613.         ed->stab = ed->argptr.arg_stab;
  4614.         ed->str = stab_array(ed->argptr.arg_stab)->ary_magic;
  4615.         if (ed->optype != O_SASSIGN || ed->argflags & (AF_PRE|AF_POST))
  4616.         str_numset(ed->str,(double)(stab_array(ed->stab)->ary_fill+arybase));
  4617. #ifdef DEBUGGING
  4618.         ed->tmps = "LARYLEN";
  4619. #endif
  4620.         if (!ed->str)
  4621.         fatal("panic: A_LEXPR");
  4622.         goto do_crement;
  4623.     case A_ARYLEN:
  4624.         ed->stab = ed->argptr.arg_stab;
  4625.         ed->st[++ed->sp] = stab_array(ed->stab)->ary_magic;
  4626.         str_numset(ed->st[ed->sp],(double)(stab_array(ed->stab)->ary_fill+arybase));
  4627. #ifdef DEBUGGING
  4628.         ed->tmps = "ARYLEN";
  4629. #endif
  4630.         break;
  4631.     case A_SINGLE:
  4632.         ed->st[++ed->sp] = ed->argptr.arg_str;
  4633. #ifdef DEBUGGING
  4634.         ed->tmps = "SINGLE";
  4635. #endif
  4636.         break;
  4637.     case A_DOUBLE:
  4638.         (void) interp(ed->str,ed->argptr.arg_str,ed->sp);
  4639.         ed->st = stack->ary_array;
  4640.         ed->st[++ed->sp] = ed->str;
  4641. #ifdef DEBUGGING
  4642.         ed->tmps = "DOUBLE";
  4643. #endif
  4644.         break;
  4645.     case A_BACKTICK:
  4646.         ed->tmps = str_get(interp(ed->str,ed->argptr.arg_str,ed->sp));
  4647.         ed->st = stack->ary_array;
  4648.         ed->fp = mypopen(ed->tmps,"r");
  4649.         str_set(ed->str,"");
  4650.         if (ed->fp) {
  4651.         if (ed->gimme == G_SCALAR) {
  4652.             while (str_gets(ed->str,ed->fp,ed->str->str_cur) != Nullch)
  4653.             /*SUPPRESS 530*/
  4654.             ;
  4655.         }
  4656.         else {
  4657.             for (;;) {
  4658.             if (++ed->sp > stack->ary_max) {
  4659.                 astore(stack, ed->sp, Nullstr);
  4660.                 ed->st = stack->ary_array;
  4661.             }
  4662.             ed->str = ed->st[ed->sp] = Str_new(56,80);
  4663.             if (str_gets(ed->str,ed->fp,0) == Nullch) {
  4664.                 ed->sp--;
  4665.                 break;
  4666.             }
  4667.             if (ed->str->str_len - ed->str->str_cur > 20) {
  4668.                 ed->str->str_len = ed->str->str_cur+1;
  4669.                 Renew(ed->str->str_ptr, ed->str->str_len, char);
  4670.             }
  4671.             str_2mortal(ed->str);
  4672.             }
  4673.         }
  4674.         statusvalue = mypclose(ed->fp);
  4675.         }
  4676.         else
  4677.         statusvalue = -1;
  4678.  
  4679.         if (ed->gimme == G_SCALAR)
  4680.         ed->st[++ed->sp] = ed->str;
  4681. #ifdef DEBUGGING
  4682.         ed->tmps = "BACK";
  4683. #endif
  4684.         break;
  4685.     case A_WANTARRAY:
  4686.         {
  4687.         if (curcsv->wantarray == G_ARRAY)
  4688.             ed->st[++ed->sp] = &str_yes;
  4689.         else
  4690.             ed->st[++ed->sp] = &str_no;
  4691.         }
  4692. #ifdef DEBUGGING
  4693.         ed->tmps = "WANTARRAY";
  4694. #endif
  4695.         break;
  4696.     case A_INDREAD:
  4697.         last_in_stab = stabent(str_get(STAB_STR(ed->argptr.arg_stab)),TRUE);
  4698.         old_rschar = rschar;
  4699.         old_rslen = rslen;
  4700.         goto do_read;
  4701.     case A_GLOB:
  4702.         ed->argflags |= AF_POST;    /* enable newline chopping */
  4703.         last_in_stab = ed->argptr.arg_stab;
  4704.         old_rschar = rschar;
  4705.         old_rslen = rslen;
  4706.         rslen = 1;
  4707.         rschar = '\n';
  4708.         goto do_read;
  4709.     case A_READ:
  4710.         last_in_stab = ed->argptr.arg_stab;
  4711.         old_rschar = rschar;
  4712.         old_rslen = rslen;
  4713.       do_read:
  4714.         if (ed->anum > 1)        /* assign to scalar */
  4715.         ed->gimme = G_SCALAR;    /* force context to scalar */
  4716.         if (ed->gimme == G_ARRAY)
  4717.         ed->str = Str_new(57,0);
  4718.         ++ed->sp;
  4719.         ed->fp = Nullfp;
  4720.         if (stab_io(last_in_stab)) {
  4721.         ed->fp = stab_io(last_in_stab)->ifp;
  4722.         if (!ed->fp) {
  4723.             if (stab_io(last_in_stab)->flags & IOF_ARGV) {
  4724.             if (stab_io(last_in_stab)->flags & IOF_START) {
  4725.                 stab_io(last_in_stab)->flags &= ~IOF_START;
  4726.                 stab_io(last_in_stab)->lines = 0;
  4727.                 if (alen(stab_array(last_in_stab)) < 0) {
  4728.                 ed->tmpstr = str_make("-",1); /* assume stdin */
  4729.                 (void)apush(stab_array(last_in_stab), ed->tmpstr);
  4730.                 }
  4731.             }
  4732.             ed->fp = nextargv(last_in_stab);
  4733.             if (!ed->fp) { /* Note: ed->fp != stab_io(last_in_stab)->ifp */
  4734.                 (void)do_close(last_in_stab,FALSE); /* now it does*/
  4735.                 stab_io(last_in_stab)->flags |= IOF_START;
  4736.             }
  4737.             }
  4738.             else if (ed->argtype == A_GLOB) {
  4739.             (void) interp(ed->str,stab_val(last_in_stab),ed->sp);
  4740.             ed->st = stack->ary_array;
  4741.             ed->tmpstr = Str_new(55,0);
  4742.             str_set(ed->tmpstr, "Echo ");
  4743.             str_scat(ed->tmpstr, ed->str);
  4744.             str_cat(ed->tmpstr," |");
  4745.             (void)do_open(last_in_stab,ed->tmpstr->str_ptr,
  4746.               ed->tmpstr->str_cur);
  4747.             ed->fp = stab_io(last_in_stab)->ifp;
  4748.             str_free(ed->tmpstr);
  4749.             }
  4750.         }
  4751.         }
  4752.         if (!ed->fp && dowarn)
  4753.         warn("Read on closed filehandle <%s>",stab_name(last_in_stab));
  4754.         ed->longo = ed->str->str_len;    /* remember if already alloced */
  4755.         if (!ed->longo)
  4756.         Str_Grow(ed->str,80);    /* try short-buffering it */
  4757.       keepgoing:
  4758.         if (!ed->fp)
  4759.         ed->st[ed->sp] = &str_undef;
  4760.         else if (!str_gets(ed->str,ed->fp, ed->optype == O_RCAT ? ed->str->str_cur : 0)) {
  4761.         clearerr(ed->fp);
  4762.         if (stab_io(last_in_stab)->flags & IOF_ARGV) {
  4763.             ed->fp = nextargv(last_in_stab);
  4764.             if (ed->fp)
  4765.             goto keepgoing;
  4766.             (void)do_close(last_in_stab,FALSE);
  4767.             stab_io(last_in_stab)->flags |= IOF_START;
  4768.         }
  4769.         else if (ed->argflags & AF_POST) {
  4770.             (void)do_close(last_in_stab,FALSE);
  4771.         }
  4772.         ed->st[ed->sp] = &str_undef;
  4773.         rschar = old_rschar;
  4774.         rslen = old_rslen;
  4775.         if (ed->gimme == G_ARRAY) {
  4776.             --ed->sp;
  4777.             str_2mortal(ed->str);
  4778.             goto array_return;
  4779.         }
  4780.         break;
  4781.         }
  4782.         else {
  4783.         stab_io(last_in_stab)->lines++;
  4784.         ed->st[ed->sp] = ed->str;
  4785.         if (ed->argflags & AF_POST) {
  4786.             if (ed->str->str_cur > 0)
  4787.             ed->str->str_cur--;
  4788.             if (ed->str->str_ptr[ed->str->str_cur] == rschar)
  4789.             ed->str->str_ptr[ed->str->str_cur] = '\0';
  4790.             else
  4791.             ed->str->str_cur++;
  4792.             for (ed->tmps = ed->str->str_ptr; *ed->tmps; ed->tmps++)
  4793.             if (!isALPHA(*ed->tmps) && !isDIGIT(*ed->tmps) &&
  4794.                 index("$&*(){}[]'\";\\|?<>~`",*ed->tmps))
  4795.                 break;
  4796.             if (*ed->tmps && stat(ed->str->str_ptr,&statbuf) < 0)
  4797.             goto keepgoing;        /* unmatched wildcard? */
  4798.         }
  4799.         if (ed->gimme == G_ARRAY) {
  4800.             if (ed->str->str_len - ed->str->str_cur > 20) {
  4801.             ed->str->str_len = ed->str->str_cur+1;
  4802.             Renew(ed->str->str_ptr, ed->str->str_len, char);
  4803.             }
  4804.             str_2mortal(ed->str);
  4805.             if (++ed->sp > stack->ary_max) {
  4806.             astore(stack, ed->sp, Nullstr);
  4807.             ed->st = stack->ary_array;
  4808.             }
  4809.             ed->str = Str_new(58,80);
  4810.             goto keepgoing;
  4811.         }
  4812.         else if (!ed->longo && ed->str->str_len - ed->str->str_cur > 80) {
  4813.             /* try to reclaim a bit of scalar space on 1st alloc */
  4814.             if (ed->str->str_cur < 60)
  4815.             ed->str->str_len = 80;
  4816.             else
  4817.             ed->str->str_len = ed->str->str_cur+40;    /* allow some slop */
  4818.             Renew(ed->str->str_ptr, ed->str->str_len, char);
  4819.         }
  4820.         }
  4821.         rschar = old_rschar;
  4822.         rslen = old_rslen;
  4823. #ifdef DEBUGGING
  4824.         ed->tmps = "READ";
  4825. #endif
  4826.         break;
  4827.     }
  4828. #ifdef DEBUGGING
  4829.     if (debug & 8)
  4830.         deb("%d.%s = '%s'\n",ed->anum,ed->tmps,str_peek(ed->st[ed->sp]));
  4831. #endif
  4832.     if (ed->anum < 8)
  4833.         ed->arglast[ed->anum] = ed->sp;
  4834.     }
  4835.  
  4836.     ed->st += ed->arglast[0];
  4837.     if (ed->optype < O_PACK)
  4838.         switch (eval1(ed)) {
  4839.         case R_nojump:
  4840.             break;
  4841.         case R_array_return:
  4842.             goto array_return;
  4843.         case R_say_no:
  4844.             goto say_no;
  4845.         case R_re_eval:
  4846.             goto re_eval;
  4847.         case R_badsock:
  4848.             goto badsock;
  4849.         case R_say_yes:
  4850.             goto say_yes;
  4851.         case R_say_undef:
  4852.             goto say_undef;
  4853.         case R_donumset:
  4854.             goto donumset;
  4855.         case R_say_zero:
  4856.             goto say_zero;
  4857.         default:
  4858.             fatal("\pOops !");
  4859.         }
  4860.     else if (ed->optype < O_CHOWN)
  4861.         switch (eval2(ed)) {
  4862.         case R_nojump:
  4863.             break;
  4864.         case R_array_return:
  4865.             goto array_return;
  4866.         case R_say_no:
  4867.             goto say_no;
  4868.         case R_re_eval:
  4869.             goto re_eval;
  4870.         case R_badsock:
  4871.             goto badsock;
  4872.         case R_say_yes:
  4873.             goto say_yes;
  4874.         case R_say_undef:
  4875.             goto say_undef;
  4876.         case R_donumset:
  4877.             goto donumset;
  4878.         case R_say_zero:
  4879.             goto say_zero;
  4880.         default:
  4881.             fatal("\pOops !");
  4882.         }
  4883.     else
  4884.     switch (ed->optype) {
  4885.     case O_CHOWN:
  4886. #ifdef HAS_CHOWN
  4887.     ed->value = (double)apply(ed->optype,ed->arglast);
  4888.     goto donumset;
  4889. #else
  4890.     fatal("Unsupported function chown");
  4891.     break;
  4892. #endif
  4893.     case O_KILL:
  4894.     fatal("Unsupported function kill");
  4895.     break;
  4896.     case O_UNLINK:
  4897.     case O_CHMOD:
  4898.     case O_UTIME:
  4899.     ed->value = (double)apply(ed->optype,ed->arglast);
  4900.     goto donumset;
  4901.     case O_UMASK:
  4902.     fatal("Unsupported function umask");
  4903.     break;
  4904. #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
  4905.     case O_MSGGET:
  4906.     case O_SHMGET:
  4907.     case O_SEMGET:
  4908.     if ((ed->anum = do_ipcget(ed->optype, ed->arglast)) == -1)
  4909.         goto say_undef;
  4910.     ed->value = (double)ed->anum;
  4911.     goto donumset;
  4912.     case O_MSGCTL:
  4913.     case O_SHMCTL:
  4914.     case O_SEMCTL:
  4915.     ed->anum = do_ipcctl(ed->optype, ed->arglast);
  4916.     if (ed->anum == -1)
  4917.         goto say_undef;
  4918.     if (ed->anum != 0) {
  4919.         ed->value = (double)ed->anum;
  4920.         goto donumset;
  4921.     }
  4922.     str_set(ed->str,"0 but true");
  4923.     STABSET(ed->str);
  4924.     break;
  4925.     case O_MSGSND:
  4926.     ed->value = (double)(do_msgsnd(ed->arglast) >= 0);
  4927.     goto donumset;
  4928.     case O_MSGRCV:
  4929.     ed->value = (double)(do_msgrcv(ed->arglast) >= 0);
  4930.     goto donumset;
  4931.     case O_SEMOP:
  4932.     ed->value = (double)(do_semop(ed->arglast) >= 0);
  4933.     goto donumset;
  4934.     case O_SHMREAD:
  4935.     case O_SHMWRITE:
  4936.     ed->value = (double)(do_shmio(ed->optype, ed->arglast) >= 0);
  4937.     goto donumset;
  4938. #else /* not SYSVIPC */
  4939.     case O_MSGGET:
  4940.     case O_MSGCTL:
  4941.     case O_MSGSND:
  4942.     case O_MSGRCV:
  4943.     case O_SEMGET:
  4944.     case O_SEMCTL:
  4945.     case O_SEMOP:
  4946.     case O_SHMGET:
  4947.     case O_SHMCTL:
  4948.     case O_SHMREAD:
  4949.     case O_SHMWRITE:
  4950.     fatal("System V IPC is not implemented on this machine");
  4951. #endif /* not SYSVIPC */
  4952.     case O_RENAME:
  4953.     ed->tmps = str_get(ed->st[1]);
  4954.     ed->tmps2 = str_get(ed->st[2]);
  4955.     ed->value = (double)(rename(ed->tmps,ed->tmps2) >= 0);
  4956.     goto donumset;
  4957.     case O_LINK:
  4958.     fatal("Unsupported function link");
  4959.     break;
  4960.     case O_MKDIR:
  4961.     ed->tmps = str_get(ed->st[1]);
  4962.     ed->anum = (int)str_gnum(ed->st[2]);
  4963.     ed->value = (double)(mkdir(ed->tmps) >= 0);
  4964.     goto donumset;
  4965.     case O_RMDIR:
  4966.     if (ed->maxarg < 1)
  4967.         ed->tmps = str_get(stab_val(defstab));
  4968.     else
  4969.         ed->tmps = str_get(ed->st[1]);
  4970.     ed->value = (double)(rmdir(ed->tmps) >= 0);
  4971.     goto donumset;
  4972.     case O_GETPPID:
  4973.     fatal("Unsupported function getppid");
  4974.     break;
  4975.     case O_GETPGRP:
  4976.     fatal("The getpgrp() function is unimplemented on this machine");
  4977.     break;
  4978.     case O_SETPGRP:
  4979.     fatal("The setpgrp() function is unimplemented on this machine");
  4980.     break;
  4981.     case O_GETPRIORITY:
  4982.     fatal("The getpriority() function is unimplemented on this machine");
  4983.     break;
  4984.     case O_SETPRIORITY:
  4985.     fatal("The setpriority() function is unimplemented on this machine");
  4986.     break;
  4987.     case O_CHROOT:
  4988.     fatal("Unsupported function chroot");
  4989.     break;
  4990.     case O_FCNTL:
  4991.     case O_IOCTL:
  4992.     if (ed->maxarg <= 0)
  4993.         ed->stab = last_in_stab;
  4994.     else if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  4995.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  4996.     else
  4997.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  4998.     ed->argtype = U_I(str_gnum(ed->st[2]));
  4999.     ed->anum = do_ctl(ed->optype,ed->stab,ed->argtype,ed->st[3]);
  5000.     if (ed->anum == -1)
  5001.         goto say_undef;
  5002.     if (ed->anum != 0) {
  5003.         ed->value = (double)ed->anum;
  5004.         goto donumset;
  5005.     }
  5006.     str_set(ed->str,"0 but true");
  5007.     STABSET(ed->str);
  5008.     break;
  5009.     case O_FLOCK:
  5010. #ifdef HAS_FLOCK
  5011.     if (ed->maxarg <= 0)
  5012.         ed->stab = last_in_stab;
  5013.     else if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  5014.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  5015.     else
  5016.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  5017.     if (ed->stab && stab_io(ed->stab))
  5018.         ed->fp = stab_io(ed->stab)->ifp;
  5019.     else
  5020.         ed->fp = Nullfp;
  5021.     if (ed->fp) {
  5022.         ed->argtype = (int)str_gnum(ed->st[2]);
  5023.         ed->value = (double)(flock(fileno(ed->fp),ed->argtype) >= 0);
  5024.     }
  5025.     else
  5026.         ed->value = 0;
  5027.     goto donumset;
  5028. #else
  5029.     fatal("The flock() function is unimplemented on this machine");
  5030.     break;
  5031. #endif
  5032.     case O_UNSHIFT:
  5033.     ed->ary = stab_array(ed->arg[1].arg_ptr.arg_stab);
  5034.     if (ed->arglast[2] - ed->arglast[1] != 1)
  5035.         do_unshift(ed->ary,ed->arglast);
  5036.     else {
  5037.         STR *    tmpstr = Str_new(52,0);    /* must copy the ed->str */
  5038.         str_sset(tmpstr,ed->st[2]);
  5039.         aunshift(ed->ary,1);
  5040.         (void)astore(ed->ary,0,tmpstr);
  5041.     }
  5042.     ed->value = (double)(ed->ary->ary_fill + 1);
  5043.     goto donumset;
  5044.  
  5045.     case O_TRY:
  5046.     sp = do_try(ed->arg[1].arg_ptr.arg_cmd,
  5047.         ed->gimme,ed->arglast);
  5048.     goto array_return;
  5049.  
  5050.     case O_EVALONCE:
  5051.     sp = do_eval(ed->st[1], O_EVAL, curcmd->c_stash, TRUE,
  5052.         ed->gimme,ed->arglast);
  5053.     if (eval_root) {
  5054.         str_free(ed->arg[1].arg_ptr.arg_str);
  5055.         ed->arg[1].arg_ptr.arg_cmd = eval_root;
  5056.         ed->arg[1].arg_type = (A_CMD|A_DONT);
  5057.         ed->arg[0].arg_type = O_TRY;
  5058.     }
  5059.     goto array_return;
  5060.  
  5061.     case O_REQUIRE:
  5062.     case O_DOFILE:
  5063.     case O_EVAL:
  5064.     if (ed->maxarg < 1)
  5065.         ed->tmpstr = stab_val(defstab);
  5066.     else
  5067.         ed->tmpstr =
  5068.           (ed->arg[1].arg_type & A_MASK) != A_NULL ? ed->st[1] : stab_val(defstab);
  5069.     ed->sp = do_eval(ed->tmpstr, ed->optype, curcmd->c_stash, FALSE,
  5070.         ed->gimme,ed->arglast);
  5071.     goto array_return;
  5072.  
  5073.     case O_FTRREAD:
  5074.     ed->argtype = 0;
  5075.     ed->anum = S_IRUSR;
  5076.     goto check_perm;
  5077.     case O_FTRWRITE:
  5078.     ed->argtype = 0;
  5079.     ed->anum = S_IWUSR;
  5080.     goto check_perm;
  5081.     case O_FTREXEC:
  5082.     ed->argtype = 0;
  5083.     ed->anum = S_IXUSR;
  5084.     goto check_perm;
  5085.     case O_FTEREAD:
  5086.     ed->argtype = 1;
  5087.     ed->anum = S_IRUSR;
  5088.     goto check_perm;
  5089.     case O_FTEWRITE:
  5090.     ed->argtype = 1;
  5091.     ed->anum = S_IWUSR;
  5092.     goto check_perm;
  5093.     case O_FTEEXEC:
  5094.     ed->argtype = 1;
  5095.     ed->anum = S_IXUSR;
  5096.       check_perm:
  5097.     if (mystat(ed->arg,ed->st[1]) < 0)
  5098.         goto say_undef;
  5099.     if (cando(ed->anum,ed->argtype,&statcache))
  5100.         goto say_yes;
  5101.     goto say_no;
  5102.  
  5103.     case O_FTIS:
  5104.     if (mystat(ed->arg,ed->st[1]) < 0)
  5105.         goto say_undef;
  5106.     goto say_yes;
  5107.     case O_FTEOWNED:
  5108.     case O_FTROWNED:
  5109.     if (mystat(ed->arg,ed->st[1]) < 0)
  5110.         goto say_undef;
  5111.     else
  5112.         goto say_yes;
  5113.     case O_FTZERO:
  5114.     if (mystat(ed->arg,ed->st[1]) < 0)
  5115.         goto say_undef;
  5116.     if (!statcache.st_size)
  5117.         goto say_yes;
  5118.     goto say_no;
  5119.     case O_FTSIZE:
  5120.     if (mystat(ed->arg,ed->st[1]) < 0)
  5121.         goto say_undef;
  5122.     ed->value = (double)statcache.st_size;
  5123.     goto donumset;
  5124.  
  5125.     case O_FTMTIME:
  5126.     if (mystat(ed->arg,ed->st[1]) < 0)
  5127.         goto say_undef;
  5128.     ed->value = (double)(basetime - statcache.st_mtime) / 86400.0;
  5129.     goto donumset;
  5130.     case O_FTATIME:
  5131.     if (mystat(ed->arg,ed->st[1]) < 0)
  5132.         goto say_undef;
  5133.     ed->value = (double)(basetime - statcache.st_atime) / 86400.0;
  5134.     goto donumset;
  5135.     case O_FTCTIME:
  5136.     if (mystat(ed->arg,ed->st[1]) < 0)
  5137.         goto say_undef;
  5138.     ed->value = (double)(basetime - statcache.st_ctime) / 86400.0;
  5139.     goto donumset;
  5140.  
  5141.     case O_FTSOCK:
  5142.     if (mystat(ed->arg,ed->st[1]) < 0)
  5143.         goto say_undef;
  5144.     if (S_ISSOCK(statcache.st_mode))
  5145.         goto say_yes;
  5146.     goto say_no;
  5147.     case O_FTCHR:
  5148.     if (mystat(ed->arg,ed->st[1]) < 0)
  5149.         goto say_undef;
  5150.     if (S_ISCHR(statcache.st_mode))
  5151.         goto say_yes;
  5152.     goto say_no;
  5153.     case O_FTBLK:
  5154.     if (mystat(ed->arg,ed->st[1]) < 0)
  5155.         goto say_undef;
  5156.     if (S_ISBLK(statcache.st_mode))
  5157.         goto say_yes;
  5158.     goto say_no;
  5159.     case O_FTFILE:
  5160.     if (mystat(ed->arg,ed->st[1]) < 0)
  5161.         goto say_undef;
  5162.     if (S_ISREG(statcache.st_mode))
  5163.         goto say_yes;
  5164.     goto say_no;
  5165.     case O_FTDIR:
  5166.     if (mystat(ed->arg,ed->st[1]) < 0)
  5167.         goto say_undef;
  5168.     if (S_ISDIR(statcache.st_mode))
  5169.         goto say_yes;
  5170.     goto say_no;
  5171.     case O_FTPIPE:
  5172.     if (mystat(ed->arg,ed->st[1]) < 0)
  5173.         goto say_undef;
  5174.     if (S_ISFIFO(statcache.st_mode))
  5175.         goto say_yes;
  5176.     goto say_no;
  5177.     case O_FTLINK:
  5178.     if (mylstat(ed->arg,ed->st[1]) < 0)
  5179.         goto say_undef;
  5180.     if (S_ISLNK(statcache.st_mode))
  5181.         goto say_yes;
  5182.     goto say_no;
  5183.     case O_SYMLINK:
  5184. #ifdef HAS_SYMLINK
  5185.     ed->tmps = str_get(ed->st[1]);
  5186.     ed->tmps2 = str_get(ed->st[2]);
  5187.     ed->value = (double)(symlink(ed->tmps,ed->tmps2) >= 0);
  5188.     goto donumset;
  5189. #else
  5190.     fatal("Unsupported function symlink");
  5191. #endif
  5192.     case O_READLINK:
  5193. #ifdef HAS_SYMLINK
  5194.     if (ed->maxarg < 1)
  5195.         ed->tmps = str_get(stab_val(defstab));
  5196.     else
  5197.         ed->tmps = str_get(ed->st[1]);
  5198.     ed->anum = readlink(ed->tmps,buf,sizeof buf);
  5199.     if (ed->anum < 0)
  5200.         goto say_undef;
  5201.     str_nset(ed->str,buf,ed->anum);
  5202.     break;
  5203. #else
  5204.     goto say_undef;        /* just pretend it's a normal file */
  5205. #endif
  5206.     case O_FTSUID:
  5207. #ifdef S_ISUID
  5208.     ed->anum = S_ISUID;
  5209.     goto check_xid;
  5210. #else
  5211.     goto say_no;
  5212. #endif
  5213.     case O_FTSGID:
  5214. #ifdef S_ISGID
  5215.     ed->anum = S_ISGID;
  5216.     goto check_xid;
  5217. #else
  5218.     goto say_no;
  5219. #endif
  5220.     case O_FTSVTX:
  5221. #ifdef S_ISVTX
  5222.     ed->anum = S_ISVTX;
  5223. #else
  5224.     goto say_no;
  5225. #endif
  5226.       check_xid:
  5227.     if (mystat(ed->arg,ed->st[1]) < 0)
  5228.         goto say_undef;
  5229.     if (statcache.st_mode & ed->anum)
  5230.         goto say_yes;
  5231.     goto say_no;
  5232.     case O_FTTTY:
  5233.     if (ed->arg[1].arg_type & A_DONT) {
  5234.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  5235.         ed->tmps = "";
  5236.     }
  5237.     else
  5238.         ed->stab = stabent(ed->tmps = str_get(ed->st[1]),FALSE);
  5239.     if (ed->stab && stab_io(ed->stab) && stab_io(ed->stab)->ifp)
  5240.         ed->anum = fileno(stab_io(ed->stab)->ifp);
  5241.     else if (isDIGIT(*ed->tmps))
  5242.         ed->anum = atoi(ed->tmps);
  5243.     else
  5244.         goto say_undef;
  5245.     if (isatty(ed->anum))
  5246.         goto say_yes;
  5247.     goto say_no;
  5248.     case O_FTTEXT:
  5249.     case O_FTBINARY:
  5250.     ed->str = do_fttext(ed->arg,ed->st[1]);
  5251.     break;
  5252. #ifdef HAS_SOCKET
  5253.     case O_SOCKET:
  5254.     if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  5255.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  5256.     else
  5257.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  5258.     ed->value = (double)do_socket(ed->stab,ed->arglast);
  5259.     goto donumset;
  5260.     case O_BIND:
  5261.     if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  5262.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  5263.     else
  5264.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  5265.     ed->value = (double)do_bind(ed->stab,ed->arglast);
  5266.     goto donumset;
  5267.     case O_CONNECT:
  5268.     if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  5269.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  5270.     else
  5271.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  5272.     ed->value = (double)do_connect(ed->stab,ed->arglast);
  5273.     goto donumset;
  5274.     case O_LISTEN:
  5275.     if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  5276.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  5277.     else
  5278.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  5279.     ed->value = (double)do_listen(ed->stab,ed->arglast);
  5280.     goto donumset;
  5281.     case O_ACCEPT:
  5282.     if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  5283.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  5284.     else
  5285.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  5286.     if ((ed->arg[2].arg_type & A_MASK) == A_WORD)
  5287.         stab2 = ed->arg[2].arg_ptr.arg_stab;
  5288.     else
  5289.         stab2 = stabent(str_get(ed->st[2]),TRUE);
  5290.     do_accept(ed->str,ed->stab,stab2);
  5291.     STABSET(ed->str);
  5292.     break;
  5293.     case O_GHBYNAME:
  5294.     if (ed->maxarg < 1)
  5295.         goto say_undef;
  5296.     case O_GHBYADDR:
  5297.     case O_GHOSTENT:
  5298.     ed->sp = do_ghent(ed->optype,
  5299.       ed->gimme,ed->arglast);
  5300.     goto array_return;
  5301.     case O_GNBYNAME:
  5302.     if (ed->maxarg < 1)
  5303.         goto say_undef;
  5304.     case O_GNBYADDR:
  5305.     case O_GNETENT:
  5306.     ed->sp = do_gnent(ed->optype,
  5307.       ed->gimme,ed->arglast);
  5308.     goto array_return;
  5309.     case O_GPBYNAME:
  5310.     if (ed->maxarg < 1)
  5311.         goto say_undef;
  5312.     case O_GPBYNUMBER:
  5313.     case O_GPROTOENT:
  5314.     ed->sp = do_gpent(ed->optype,
  5315.       ed->gimme,ed->arglast);
  5316.     goto array_return;
  5317.     case O_GSBYNAME:
  5318.     if (ed->maxarg < 1)
  5319.         goto say_undef;
  5320.     case O_GSBYPORT:
  5321.     case O_GSERVENT:
  5322.     ed->sp = do_gsent(ed->optype,
  5323.       ed->gimme,ed->arglast);
  5324.     goto array_return;
  5325.     case O_SHOSTENT:
  5326.     ed->value = (double) sethostent((int)str_gnum(ed->st[1]));
  5327.     goto donumset;
  5328.     case O_SNETENT:
  5329.     ed->value = (double) setnetent((int)str_gnum(ed->st[1]));
  5330.     goto donumset;
  5331.     case O_SPROTOENT:
  5332.     ed->value = (double) setprotoent((int)str_gnum(ed->st[1]));
  5333.     goto donumset;
  5334.     case O_SSERVENT:
  5335.     ed->value = (double) setservent((int)str_gnum(ed->st[1]));
  5336.     goto donumset;
  5337.     case O_EHOSTENT:
  5338.     ed->value = (double) endhostent();
  5339.     goto donumset;
  5340.     case O_ENETENT:
  5341.     ed->value = (double) endnetent();
  5342.     goto donumset;
  5343.     case O_EPROTOENT:
  5344.     ed->value = (double) endprotoent();
  5345.     goto donumset;
  5346.     case O_ESERVENT:
  5347.     ed->value = (double) endservent();
  5348.     goto donumset;
  5349.     case O_SOCKPAIR:
  5350.     if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  5351.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  5352.     else
  5353.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  5354.     if ((ed->arg[2].arg_type & A_MASK) == A_WORD)
  5355.         stab2 = ed->arg[2].arg_ptr.arg_stab;
  5356.     else
  5357.         stab2 = stabent(str_get(ed->st[2]),TRUE);
  5358.     ed->value = (double)do_spair(ed->stab,stab2,ed->arglast);
  5359.     goto donumset;
  5360.     case O_SHUTDOWN:
  5361.     if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  5362.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  5363.     else
  5364.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  5365.     ed->value = (double)do_shutdown(ed->stab,ed->arglast);
  5366.     goto donumset;
  5367.     case O_GSOCKOPT:
  5368.     case O_SSOCKOPT:
  5369.     if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  5370.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  5371.     else
  5372.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  5373.     ed->sp = do_sopt(ed->optype,ed->stab,ed->arglast);
  5374.     goto array_return;
  5375.     case O_GETSOCKNAME:
  5376.     case O_GETPEERNAME:
  5377.     if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  5378.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  5379.     else
  5380.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  5381.     if (!ed->stab)
  5382.         goto say_undef;
  5383.     ed->sp = do_getsockname(ed->optype,ed->stab,ed->arglast);
  5384.     goto array_return;
  5385.  
  5386. #else /* HAS_SOCKET not defined */
  5387.     case O_SOCKET:
  5388.     case O_BIND:
  5389.     case O_CONNECT:
  5390.     case O_LISTEN:
  5391.     case O_ACCEPT:
  5392.     case O_SOCKPAIR:
  5393.     case O_GHBYNAME:
  5394.     case O_GHBYADDR:
  5395.     case O_GHOSTENT:
  5396.     case O_GNBYNAME:
  5397.     case O_GNBYADDR:
  5398.     case O_GNETENT:
  5399.     case O_GPBYNAME:
  5400.     case O_GPBYNUMBER:
  5401.     case O_GPROTOENT:
  5402.     case O_GSBYNAME:
  5403.     case O_GSBYPORT:
  5404.     case O_GSERVENT:
  5405.     case O_SHOSTENT:
  5406.     case O_SNETENT:
  5407.     case O_SPROTOENT:
  5408.     case O_SSERVENT:
  5409.     case O_EHOSTENT:
  5410.     case O_ENETENT:
  5411.     case O_EPROTOENT:
  5412.     case O_ESERVENT:
  5413.     case O_SHUTDOWN:
  5414.     case O_GSOCKOPT:
  5415.     case O_SSOCKOPT:
  5416.     case O_GETSOCKNAME:
  5417.     case O_GETPEERNAME:
  5418.       badsock:
  5419.     fatal("Unsupported socket function");
  5420. #endif /* HAS_SOCKET */
  5421.     case O_SSELECT:
  5422. #ifdef HAS_SELECT
  5423.     ed->sp = do_select(ed->gimme,ed->arglast);
  5424.     goto array_return;
  5425. #else
  5426.     fatal("select not implemented");
  5427. #endif
  5428.     case O_FILENO:
  5429.     if (ed->maxarg < 1)
  5430.         goto say_undef;
  5431.     if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  5432.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  5433.     else
  5434.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  5435.     if (!ed->stab || !(stio = stab_io(ed->stab)) || !(ed->fp = stio->ifp))
  5436.         goto say_undef;
  5437.     ed->value = fileno(ed->fp);
  5438.     goto donumset;
  5439.     case O_BINMODE:
  5440.     if (ed->maxarg < 1)
  5441.         goto say_undef;
  5442.     if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  5443.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  5444.     else
  5445.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  5446.     if (!ed->stab || !(stio = stab_io(ed->stab)) || !(ed->fp = stio->ifp))
  5447.         goto say_undef;
  5448.     str_set(ed->str, Yes);
  5449.     STABSET(ed->str);
  5450.     break;
  5451.     case O_VEC:
  5452.     ed->sp = do_vec(ed->str == ed->st[1], ed->arg->arg_ptr.arg_str, ed->arglast);
  5453.     goto array_return;
  5454.     case O_GPWNAM:
  5455.     case O_GPWUID:
  5456.     case O_GPWENT:
  5457. #ifdef HAS_PASSWD
  5458.     ed->sp = do_gpwent(ed->optype,
  5459.       ed->gimme,ed->arglast);
  5460.     goto array_return;
  5461.     case O_SPWENT:
  5462.     ed->value = (double) setpwent();
  5463.     goto donumset;
  5464.     case O_EPWENT:
  5465.     ed->value = (double) endpwent();
  5466.     goto donumset;
  5467. #else
  5468.     case O_EPWENT:
  5469.     case O_SPWENT:
  5470.     fatal("Unsupported password function");
  5471.     break;
  5472. #endif
  5473.     case O_GGRNAM:
  5474.     case O_GGRGID:
  5475.     case O_GGRENT:
  5476. #ifdef HAS_GROUP
  5477.     ed->sp = do_ggrent(ed->optype,
  5478.       ed->gimme,ed->arglast);
  5479.     goto array_return;
  5480.     case O_SGRENT:
  5481.     ed->value = (double) setgrent();
  5482.     goto donumset;
  5483.     case O_EGRENT:
  5484.     ed->value = (double) endgrent();
  5485.     goto donumset;
  5486. #else
  5487.     case O_EGRENT:
  5488.     case O_SGRENT:
  5489.     fatal("Unsupported group function");
  5490.     break;
  5491. #endif
  5492.     case O_GETLOGIN:
  5493. #ifdef HAS_GETLOGIN
  5494.     if (!(ed->tmps = getlogin()))
  5495.         goto say_undef;
  5496.     str_set(ed->str,ed->tmps);
  5497. #else
  5498.     fatal("Unsupported function getlogin");
  5499. #endif
  5500.     break;
  5501.     case O_OPEN_DIR:
  5502.     case O_READDIR:
  5503.     case O_TELLDIR:
  5504.     case O_SEEKDIR:
  5505.     case O_REWINDDIR:
  5506.     case O_CLOSEDIR:
  5507.     if (ed->maxarg < 1)
  5508.         goto say_undef;
  5509.     if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  5510.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  5511.     else
  5512.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  5513.     if (!ed->stab)
  5514.         goto say_undef;
  5515.     ed->sp = do_dirop(ed->optype,ed->stab,ed->gimme,ed->arglast);
  5516.     goto array_return;
  5517.     case O_SYSCALL:
  5518.     ed->value = (double)do_syscall(ed->arglast);
  5519.     goto donumset;
  5520.     case O_PIPE:
  5521. #ifdef HAS_PIPE
  5522.     if ((ed->arg[1].arg_type & A_MASK) == A_WORD)
  5523.         ed->stab = ed->arg[1].arg_ptr.arg_stab;
  5524.     else
  5525.         ed->stab = stabent(str_get(ed->st[1]),TRUE);
  5526.     if ((ed->arg[2].arg_type & A_MASK) == A_WORD)
  5527.         stab2 = ed->arg[2].arg_ptr.arg_stab;
  5528.     else
  5529.         stab2 = stabent(str_get(ed->st[2]),TRUE);
  5530.     do_pipe(ed->str,ed->stab,stab2);
  5531.     STABSET(ed->str);
  5532. #else
  5533.     fatal("Unsupported function pipe");
  5534. #endif
  5535.     break;
  5536.     }
  5537.  
  5538.   normal_return:
  5539.     ed->st[1] = ed->str;
  5540. #ifdef DEBUGGING
  5541.     if (debug) {
  5542.     dlevel--;
  5543.     if (debug & 8)
  5544.         deb("%s RETURNS \"%s\"\n",opname[ed->optype],str_get(ed->str));
  5545.     }
  5546. #endif
  5547.     return ed->arglast[0] + 1;
  5548.  
  5549. array_return:
  5550. #ifdef DEBUGGING
  5551.     if (debug) {
  5552.     dlevel--;
  5553.     if (debug & 8) {
  5554.         ed->anum = ed->sp - ed->arglast[0];
  5555.         switch (ed->anum) {
  5556.         case 0:
  5557.         deb("%s RETURNS ()\n",opname[ed->optype]);
  5558.         break;
  5559.         case 1:
  5560.         deb("%s RETURNS (\"%s\")\n",opname[ed->optype],
  5561.             st[1] ? str_get(st[1]) : "");
  5562.         break;
  5563.         default:
  5564.         ed->tmps = ed->st[1] ? str_get(ed->st[1]) : "";
  5565.         deb("%s RETURNS %d ARGS (\"%s\",%s\"%s\")\n",opname[ed->optype],
  5566.           anum,tmps,anum==2?"":"...,",
  5567.             st[anum] ? str_get(st[anum]) : "");
  5568.         break;
  5569.         }
  5570.     }
  5571.     }
  5572. #endif
  5573.     return ed->sp;
  5574.  
  5575. say_yes:
  5576.     ed->str = &str_yes;
  5577.     goto normal_return;
  5578.  
  5579. say_no:
  5580.     ed->str = &str_no;
  5581.     goto normal_return;
  5582.  
  5583. say_undef:
  5584.     ed->str = &str_undef;
  5585.     goto normal_return;
  5586.  
  5587. say_zero:
  5588.     ed->value = 0.0;
  5589.     /* FALL THROUGH */
  5590.  
  5591. donumset:
  5592.     str_numset(ed->str,ed->value);
  5593.     STABSET(ed->str);
  5594.     ed->st[1] = ed->str;
  5595. #ifdef DEBUGGING
  5596.     if (debug) {
  5597.     dlevel--;
  5598.     if (debug & 8)
  5599.         deb("%s RETURNS \"%f\"\n",opname[ed->optype],ed->value);
  5600.     }
  5601. #endif
  5602.     return ed->arglast[0] + 1;
  5603. }
  5604.  
  5605. #endif
  5606.